There is no way to directly call an internal function through function selector.
The entry point of a contract is basically a jump table with additional checks, looking for a matching function selector between the first 4 bytes of calldata and the exposed functions of the contract.
Marking your function internal excludes it from that jump table, making it inaccessible from an external call.
Take the following contract :
contract SelectorsPublic {
bool public called;
function otherFunc(bool _called) public {
called =_called;
}
}
I deployed it here. You can check the decompiled bytecode here.
With an explicit check for the function selector in the main function body (As a reminder: keccak256("otherFunc(bool)")
== 0x64feed76...
) :
else if (var0 == 0x64feed76) {
// Dispatch table entry for 0x64feed76 (unknown)
var1 = 0x0073;
var2 = 0x006e;
var4 = 0x04;
var3 = var4 + (msg.data.length - var4);
var2 = func_0109(var3, var4);
func_006E(var2);
stop();
}
By opposition, this contract (with internal visibility) :
contract SelectorsInternal {
bool public called;
function otherFunc(bool _called) internal {
called =_called;
}
}
Deployed here, and decompiled here presents no such check. Meaning that there is no path leading to otherFunc
from the main entry point of the smart contract.
Only internal calls to it will be allowed, external ones will not find a matching entry and therefore revert (or won't even compile like in your example).
EDIT : If from the decompiled bytecode you are wondering what the check for 0x50f9b6cd
are : those are just the same principle applied to the auto generated getter for : bool public called
, keccak256("called()")
= 0x50f9b6cd....
EDIT 2:
Only external (or public) functions have the following members:
.address
: returns the address of the contract of the function.
.selector
: returns the ABI function selector
So by using either of these, you are calling the functions "externally".
It seems like you forgot to reference from the library like this Library.Areas , which is why it isn't working and calling out an error.
I found an example on the official solidity doc that shows you how to use library correctly. I coded a demo that is working just fine below that works just fine.
Example code of the use case of using Library that has enum & struct.
- Tested it on remix.ethereum
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library Lib {
enum Areas {
Burrow, School, Forest, Mine, DeepMine, Trails
}
struct AreaFeatures{
string name;
}
enum Powers{
EmptyHead, BrainPower, AxeStrength, Speed, Scavenge
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./OurLibrary.sol";
contract TestingSomething {
function testingEnum(Lib.Areas _x) public pure returns (Lib.Areas) {
return _x;
}
function testingStruct() public pure returns (Lib.AreaFeatures memory) {
Lib.AreaFeatures memory y = Lib.AreaFeatures("example");
return y;
}
}
Best Answer
You'll need to know the functions parameters elementary type and use that.
For an enum, the type is
uint8
.You can determine this using the
--abi
option tosolc
(or other compilers):In cast:
Tuple/Struct Edit
Note, for a tuple or struct type, you'll need to combine the components into parentheses.
Example:
getName
would have a function selector of:0x5e492cc7
You could find it by: