you can use web3 built-in functionality:
web3.eth.abi.decodeParameters(typesArray, hexString);
see link
A function selector allows you to perform dynamic invocation of a function, based on the name of the function and the type of each one of the input arguments.
For example, suppose you have:
contract Contract1 {
function func(uint256 x, uint8 y) public returns (uint32, uint32) {...}
}
contract Contract2 {
Contract1 public contract1 = new Contract1();
function func() public returns (uint32, uint32) {...}
}
Then you can call Contract1.func
from Contract2.func
as follows:
function func() public returns (uint32, uint32) {
uint32[2] memory ret;
address dest = address(contract1);
bytes4 selector = contract1.func.selector;
// Or bytes4 selector = bytes4(uint256(keccak256("func(uint256,uint8)") >> 224));
bytes memory data = abi.encodeWithSelector(selector, uint256(789), uint8(123));
assembly {
let success := call(
gas, // pass the remaining gas to the function
dest, // the address of the contract1 instance
0, // pass 0 wei to the function
add(data, 32), // the actual data starts after the length of 'data'
mload(data), // the length of 'data' appears at the first 32 bytes
ret, // the address of the output
8 // the size of the output
)
if iszero(success) {
revert(0, 0)
}
}
return (ret[0], ret[1]);
}
If the invoked function is constant (either pure
or view
), then you can also use staticcall
.
The example above is in assembly, but you can also use call
directly in solidity.
I think that staticcall
should be available starting from solidity v0.5.0.
Best Answer
If your data was in calldata (data location) you could simply use slices. Unfortunately, slices are not available on memory arrays.
shl
doesn't care about reference or value types, it just takes a value and shifts it. Your issue is that you didn't gave it the right value :data
is a memory pointer, while you want to shift the actual data contained there.Now you will need to do a bit more than just shifting if your data is more than 32 bytes long (which is always true with dynamic types such as
string
due to the way abi encoding works).To do so, you could use the following function, which works regardless of length, type or number of arguments :
And call it to extract the part of interest :
Which outputs
hello
as expected.I hope this answers your question.