In general, you cannot just concatenate partial ABI encodings, as ABI encoding aplitssplits variable length parameters into fixed and variable parts. For function Foo the correct encoding would be:
selector (4 bytes) name offset (32 bytes) symbol offset (32 bytes) decimals (32 bytes) totalSupply (32 bytes) address (32 bytes) value (32 bytes) name length (32 bytes) name body (? bytes) symbol length (32 bytes) symbol body (? bytes) When user encodes all Foo parameters except for the last two, the encoding probably looks like this:
selector (4 bytes) name offset (32 bytes) symbol offset (32 bytes) decimals (32 bytes) totalSupply (32 bytes) name length (32 bytes) name body (? bytes) symbol length (32 bytes) symbol body (? bytes) When you append msg.sender and msg.value, you get:
selector (4 bytes) name offset (32 bytes) symbol offset (32 bytes) decimals (32 bytes) totalSupply (32 bytes) address (32 bytes) value (32 bytes) name length (32 bytes) name body (? bytes) symbol length (32 bytes) symbol body (? bytes) msg.sender (32 bytes) msg.value (32 bytes) So the result is obviously incorrect.
Correct solution would be to first decode all the parameters into separate local variables using abi.decode, and then repack the back together with msg.sender and msg.value using abi.encodeWithSignature. Something like this:
string memory name; string memory symbol; uint256 decimals; uint256 totalSupply; (name, symbol, decimals, totalSupply) = abi.decode ( data, (string, string, uint256, uint256)); bytes memory payload = abi.encodeWithSignature ( method, name, symbol, decimals, totalSupply, msg.sender, msg.value);