Skip to content

Instantly share code, notes, and snippets.

@devtooligan
Last active July 22, 2022 19:55
Show Gist options
  • Save devtooligan/621a2f0972a95313afb77e56525f0a90 to your computer and use it in GitHub Desktop.
Save devtooligan/621a2f0972a95313afb77e56525f0a90 to your computer and use it in GitHub Desktop.
passing funcs
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;
/*
Pasting this code into evm.codes playground and stepping through will show that starting on instruction 1d, the
JUMPDEST of the target function (which is 36) is pushed onto the stack. Then there is a SHL(20) performed on it.
Then it's ORed with 00b4 so 36 becomes 36000000b4.
Then later in step 47, when myFunc() calls targetFunc(), it does a SHR(20) to convert 36000000b4 back to 36 which
it then uses for the JUMPDEST to targetFunc(). Nothing is ever done with the 000000b4 part. A copy of the full
36000000b4 remains on the stack until step 4b and then its POPped off.
One clue about this is that I think the 00b4 may represent the code size? Because as I was setting up this gist
I ommitted the last two fn's inc() and dec() and the that changed the 00b4 to 004d. So my guess is that normally
fn args would be added to the end of the code but not sure.
*/
contract Counter {
uint public sixtyNine;
function myFunc(function() pure returns (uint) func) internal {
func();
}
// Function passed into myFunc
function targetFunc() internal pure returns (uint) {
return 0xbadbabe;
}
constructor() {
sixtyNine = 0x69; // useful for finding your bearings while stepping through
myFunc(targetFunc);
}
// These last two fns don't are unrelated but they were included in the original
// example shared on Twitter so including them here for consistency.
function inc() public {
sixtyNine += 1;
}
function dec() public {
sixtyNine -= 1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment