I'm currently developing a dApp locally using Hardhat and React.JS... and I'm getting a silly error that makes no sense at all.
Hardhat deploys a smart contract that allows staking ERC-20 tokens. Functions like 'stake' and 'getBonusQuantity' work perfectly, although the contracts were recently modified and I had to recompile them, get the new ABI for use in the frontend, etc.
The problem is that the 'unstakeSpecific' function doesn't work at all. It hasn't been touched in the latest contract changes at all, but now it seems the function isn't recognized.
This is the error I get from the browser console when calling the function, the addresses shown in the error are correct for the account that does the unstaking, and the contract address is also correct:
ContractFunctionExecutionError: The contract function "unstakeSpecific" reverted with the following reason: Error: Transaction reverted: function selector was not recognized and there's no fallback function Contract Call: address: 0xc6e7df5e7b4f2a278906862b61205850344d4e7d function: unstakeSpecific(uint256 index) args: (1) sender: 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC At first I thought it was a bug with MetaMask, but I set up CoinBaseWallet and I still get the same error: the selector is not recognized. So I ruled out the frontend as the cause of the error, and tried calling 'unstakeSpecific' simply from the hardhat script that deploys the contracts, and that still doesn't work at all. This is the log I get from hardhat when I call the function:
Error: cannot estimate gas; transaction may fail or may require manual gas limit [ See: https://links.ethers.org/v5-errors-UNPREDICTABLE_GAS_LIMIT ] (reason="Error: Transaction reverted: function selector was not recognized and there's no fallback function", method="estimateGas", transaction={"from":"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC","to":"0xc6e7DF5E7b4f2A278906862b61205850344D4e7d","data":"0xee5507970000000000000000000000000000000000000000000000000000000000000001","accessList":null}, error={"name":"ProviderError","_stack":"ProviderError: Error: Transaction reverted: function selector was not recognized and there's no fallback function\n at HttpProvider.request (/home/jorge/Escritorio/DEV/Proyectos/StakeAI/App/iescrow/hardhat/node_modules/hardhat/src/internal/core/providers/http.ts:116:21)\n at processTicksAndRejections (node:internal/process/task_queues:105:5)\n at async EthersProviderWrapper.send (/home/jorge/Escritorio/DEV/Proyectos/StakeAI/App/iescrow/hardhat/node_modules/@nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20)","code":-32603,"_isProviderError":true,"data":{"message":"Error: Transaction reverted: function selector was not recognized and there's no fallback function","data":"0x"}}, code=UNPREDICTABLE_GAS_LIMIT, version=providers/5.8.0) at Logger.makeError (/home/jorge/Escritorio/DEV/Proyectos/StakeAI/App/iescrow/hardhat/node_modules/@ethersproject/logger/src.ts/index.ts:269:28) at Logger.throwError (/home/jorge/Escritorio/DEV/Proyectos/StakeAI/App/iescrow/hardhat/node_modules/@ethersproject/logger/src.ts/index.ts:281:20) at checkError (/home/jorge/Escritorio/DEV/Proyectos/StakeAI/App/iescrow/hardhat/node_modules/@ethersproject/providers/src.ts/json-rpc-provider.ts:78:20) at EthersProviderWrapper.<anonymous> (/home/jorge/Escritorio/DEV/Proyectos/StakeAI/App/iescrow/hardhat/node_modules/@ethersproject/providers/src.ts/json-rpc-provider.ts:642:20) at step (/home/jorge/Escritorio/DEV/Proyectos/StakeAI/App/iescrow/hardhat/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:48:23) at Object.throw (/home/jorge/Escritorio/DEV/Proyectos/StakeAI/App/iescrow/hardhat/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:29:53) at rejected (/home/jorge/Escritorio/DEV/Proyectos/StakeAI/App/iescrow/hardhat/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:21:65) at processTicksAndRejections (node:internal/process/task_queues:105:5) { reason: "Error: Transaction reverted: function selector was not recognized and there's no fallback function", code: 'UNPREDICTABLE_GAS_LIMIT', method: 'estimateGas', transaction: { from: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC', to: '0xc6e7DF5E7b4f2A278906862b61205850344D4e7d', data: '0xee5507970000000000000000000000000000000000000000000000000000000000000001', accessList: null }, error: ProviderError: Error: Transaction reverted: function selector was not recognized and there's no fallback function at HttpProvider.request (/home/jorge/Escritorio/DEV/Proyectos/StakeAI/App/iescrow/hardhat/node_modules/hardhat/src/internal/core/providers/http.ts:116:21) at processTicksAndRejections (node:internal/process/task_queues:105:5) at async EthersProviderWrapper.send (/home/jorge/Escritorio/DEV/Proyectos/StakeAI/App/iescrow/hardhat/node_modules/@nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20) This feature worked perfectly before, but now, for no reason, it stops working and Hard Hat doesn't recognize it. I've already tried:
- Use another wallet (the problem is obviously not here)
- Delete artifacts and hardhat cache and recompile the contracts
- Check contract and account addresses
- Check ABI (see below, but there should be no problem here)
Regardless of whether I try one solution or another, the other contract functions are fine, so I don't know what's wrong with this specific function. I've been trying for HOURS to get it working, but it's not working. Here's the ABI snippet where the function interface, the function itself, is located.
ABI Fragment for this function:
{ "inputs": [ { "internalType": "uint256", "name": "index", "type": "uint256" } ], "name": "unstakeSpecific", "outputs": [], "stateMutability": "nonpayable", "type": "function" } unstakeSpecific function:
/// @notice Deshacer un stake específico (por índice) y pagar solo ese principal + reward function unstakeSpecific(uint256 index) external nonReentrant whenTreasuryHasBalance(_stakes[msg.sender][index].amount) { StakeInfo[] storage arr = _stakes[msg.sender]; require(index < arr.length, "TokenStaking: invalid stake index"); StakeInfo storage s = arr[index]; uint256 principal = s.amount; // Calcular reward pendiente de este stake uint256 currentTime = getCurrentTime(); uint256 effectiveEnd = currentTime > s.end ? s.end : currentTime; uint256 elapsed = effectiveEnd - s.lastRewardCalculation; uint256 pendingReward = 0; if (_totalStakedTokens > 0) { uint256 rewardPerSec = (REWARD_RATE * s.amount * 1e18) / _totalStakedTokens; pendingReward = (elapsed * rewardPerSec) / 1e18 + s.rewardAmount; } // Penalización temprana (si se invoca antes de s.end) uint256 fee = 0; if (currentTime < s.end) { fee = (pendingReward * _earlyUnstakeFeePercentage) / PERCENTAGE_DENOMINATOR; uint256 burnAmount = (fee * 25) / 100; // *** CORRECCIÓN: Usar dirección de quema específica en lugar de address(0) IERC20(_tokenAddress).transfer(BURN_ADDRESS, burnAmount); emit EarlyUnStakeFee(msg.sender, burnAmount); } uint256 rewardToSend = pendingReward - fee; // Actualizar totales antes de eliminar del array _totalStakedTokens -= principal; _totalPaidTokens += rewardToSend; // Swap-and-pop para eliminar este stake arr[index] = arr[arr.length - 1]; arr.pop(); if (arr.length == 0) { _totalUsers -= 1; _removeActiveUser(msg.sender); // Remover de usuarios activos } // *** CORRECCIÓN: El frontend ya maneja la conversión, no multiplicamos por 1e18 IMintableERC20(_tokenAddress).mint(msg.sender, principal); IERC20(_tokenAddress).transfer(msg.sender, rewardToSend); emit UnStake(msg.sender, principal); emit ClaimReward(msg.sender, rewardToSend); } function call from contracts deploy script:
try { const unstakeTx = await tokenStaking.connect(staker).unstakeSpecific(1); await unstakeTx.wait(); console.log(`Unstake realizado en índice 0 para ${staker.address}`); } catch (err) { console.error("Error al desestakear:", err); } As I mentioned, this worked perfectly with the previous contract; in any case, this feature wasn't changed. I honestly don't understand why these errors are generated out of nowhere, nor how to fix them. The addresses are the same for both accounts and contracts, and the ABI is correct. In short: other functions that have changed and are more complex work, but this one doesn't!
If anyone could help me, I'd appreciate it. Thanks.