hedera-sdk-js
hedera-sdk-js copied to clipboard
Signature map creation for calling precompile results in INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE
Description
The Issue:
When performing approved transfers (allowances) for FTs via the precompiles, the process does not complete as expected. The approved transfer via the precompile results in INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE
.
The FT example:
- 5 entities are involved: Operator, Treasury, Alice, Bob, and the token
- The Treasury of the token approves an allowance for Alice of 50 FT units calling the
approve
precompile ✅ - Alice should send bob 10 FT units from the allowance via the
transferToken
precompile ❌
Steps to reproduce
-
Open the following GitPod: https://gitpod.io/#https://github.com/ed-marquez/hedera-example-allowances-solidity-precompiles
-
Add a .env file with your own testnet credentials
-
Open and run the file: 0_test_precompile_FT.js
-
Notice from the token balances in the console that the delegated transfer of FT does not go through
-
See this error
INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE
in HashScan in Alice's account when trying to perform the approved transfer from Treasury to Bob (https://hashscan.io/#/testnet/transactionsById/0.0.48611794-1665689598-806197477)
Additional context
External users have also reported running into this error. Here's some input from bugbytes (Jason from Calaxy):
If you're calling a smart contract and it is in turn calling a precompiled contract, I believe you need to add the full 32bytes of public key in the signature map. Native hedera transactions do not typically need the full public key value to disambiguate signatures, but smart contracts don't have access to the key requirements like a native node transaction context does -- in other words, when calling a contract, always use the full 32bytes of the public key for the prefix to be safe.
@Nana-EC also suggested that it could be an issue arising from how the signature map is created in the SDK. Please help confirm if this is the case so we can provide appropriate guidance to other users seeing this issue.
==================
As additional context, from this other open issue, it does seem that there are two problems when a user wants to call a contract that in turn call the precompile (aka. JavaScript file that uses the SDK => Contract A => HTS Precompile):
-
INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE
error when executing the child transaction (approved transfer) due to the signature map creation in the SDK -
tokenTransfer
precompile not supporting approved transfer
I believe problems 1 and 2 to be decoupled. Please advise if that's not the case. This GH issue is about problem 1.
Hedera network
testnet
Version
2.18.3
Operating system
Windows
Actually, I think this could potentially have more to do with the use of delegatecall
within the contract and a potential mismatch between the key being signed with.
If it was an SDK signing issue it would likely affect all the call attempts.
Also noting the contract code in 0_test.sol
function ftTransferApproved(address _tokenAddress, address _owner, address _receiver, int64 _amount) external returns (int) {
// int responseCode = HederaTokenService.approve(_tokenAddress, _spender, _amount);
htsPrecompiles.delegatecall(abi.encodeWithSelector(IHederaTokenService.transferToken.selector, _tokenAddress, _owner, _receiver, _amount));
// if (responseCode != HederaResponseCodes.SUCCESS) {
// // revert ("allowance Failed");
// return responseCode;
// }
// return responseCode;
}
For an approval transfer you should be using transferFrom
selector not transfer
Given transferFrom was only recently added in 0.31 your only current option would be to utilize IERC20.transferFrom()
In follow up the sdk-js should have examples that map to calls for the contract functions under here
A current general example exists but it might be better to have examples for each method
Up until now, several scenarios were implemented on top of the provided code example to test different setups:
-
The
delegatecall
was replaced with a normalcall
in order to see if the issue comes from a mismatch between the key being signed with, as mentioned This basically resulted with the same outcome -> INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE when trying to execute the approved transfer Thus, I assume that the issue does not come from thedelegatecall
itself -
I saw that the
transferFrom
function was implemented in the hedera-services but when trying to call it from theIHederaTokenService
replacing thetokenTransfer
with it, there is not even a child transaction to theContract Call
transaction in hashscan, so I would assume it is still not on testnet
Furthermore, it is true that if you're calling a smart contract and it is in turn calling a precompiled contract you need to provide the full 32bytes of public key in the signature map source But, I believe that this is the default behavior for our SDK right now
We are still investigating the issue..
Quick update: you can achieve the wanted result by calling the transferFrom
instead of tokenTransfer
. Currently, the functionality can be tested only by running a local node
locally or on previewnet
, since the feature is present only on previewnet
atm. Should be alive on testnet
soon
I think the issue may be closed, since the tokenTransfer
should not support allowance transfers by design, correct me if I'm wrong @Nana-EC
@ed-marquez Can you try to test what @petreze listed here as a possible solution.
Thanks for looking into and addressing this.
Sounds good. I will try transferFrom
on previewnet.
I think this issue can be closed. I'll report back if any issues are found.