1

This my contract /**

contract JayTechAirdrop { address public owner; address public jayTechTokenAddress; uint256 public claimAmount = 1e6 * 1e18; // 1 million JayTech tokens uint256 public gasFee;

mapping(address => bool) public hasClaimed;

event Claim(address indexed recipient, uint256 amount);
event Withdrawal(address indexed owner, uint256 amount);

modifier onlyOwner() {
    require(msg.sender == owner, "Not the owner");
    _;
}

constructor(address _jayTechToken, uint256 _gasFee) {
    owner = msg.sender;
    jayTechTokenAddress = _jayTechToken;
    gasFee = _gasFee;
}

function claim() external {
    require(!hasClaimed[msg.sender], "Already claimed");

    // Call the internal transfer function
    _transfer(jayTechTokenAddress, msg.sender, claimAmount);
    hasClaimed[msg.sender] = true;

    emit Claim(msg.sender, claimAmount);
}

function withdrawGasFee() external onlyOwner {
    uint256 balance = address(this).balance;
    require(balance >= gasFee, "Insufficient balance");

    payable(owner).transfer(gasFee);

    emit Withdrawal(owner, gasFee);
}

// Fallback function to receive Ether (gas fee)
receive() external payable {}

// Internal ERC-20 transfer function
function _transfer(address token, address to, uint256 amount) internal {
    (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, amount));
    require(success && (data.length == 0 || abi.decode(data, (bool))), "Transfer failed");
}

// Allow anyone who deploys the contract to call the withdraw function
function withdraw(uint256 amount) external onlyOwner {
    _transfer(jayTechTokenAddress, owner, amount);
}

}

This is how i am calling the contract from my frontend:

const receipt = await airdropContract.methods .claim() .send({ from: accounts[0], gas: 50000 }); console.log(receipt); } } catch (error) { console.log("Error claiming tokens:", error); }

How can i achieve this pls, Do i need to perform an approval function? and if yes, how do i go about it because the approval is not existing in the ABI. NB:I am able to perform all the read functions using the javascript but the wriy

3 Answers 3

0

Your code is indeed correct. Also, you do not need to perform an approval function because the token should be already inside the smart contract. The error of your FE may come from that as well. Have you transferred the claimed token to the smart contract?

12
  • Yes , i have transfered token into the Airdrop contract, I am thinking the error may be coming from the gas fees i set on the airdrop contract, but does that change anything?
    – Hallenjay
    Dec 25, 2023 at 12:55
  • For best practice, you can try to execute function claim directly in blockchain scan (i.e., bscscan), if it works well. Then, your FE code has problem. If not, your Solidity code has problem :D.
    – tqdpham96
    Dec 25, 2023 at 12:57
  • the claim function is not working on polygon testnet, same as all the read function on polygon testnet because that is where i deployed the contract meanwhile all the read function are working and returning right result when i used javascript to query it
    – Hallenjay
    Dec 25, 2023 at 12:59
  • I deployed your contract and test it on bsc testnet. The function claim work pretty well and I received 1M token. Are you sure that you send the right token (jayTechTokenAddress) to the smart contract? If yes, can you provide the sc address so that I can try by my self.
    – tqdpham96
    Dec 25, 2023 at 13:13
  • This is sc address : 0x6126C8dc3395d52A4a1470773CF4987B5B20724F for the token on polygon testnet. mumbai.polygonscan.com/token/…
    – Hallenjay
    Dec 25, 2023 at 13:18
0

Here is the modified code using transferFrom (you should add this one to your token contract).

    function transferFrom(address from, address to, uint256 value)  external returns (bool) {
        require(balanceOf[from] >= value, "Insufficient balance");
        balanceOf[from] -= value;
        balanceOf[to] += value;
        emit Transfer(from, to, value);
        return true;
    }

Then, in the claim contract you add this function and change the claim function as

        // Internal ERC-20 transfer function
    function _transferFrom(address token, address to, uint256 amount) internal {
        (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0x23b872dd, address(this), to, amount));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferFrom failed");
    }

    function claim() external {
        require(!hasClaimed[msg.sender], "Already claimed");

        // Call the internal transfer function
        _transferFrom(jayTechTokenAddress, msg.sender, claimAmount);
        hasClaimed[msg.sender] = true;

        emit Claim(msg.sender, claimAmount);
    }

Here is the contract code that I deployed for your reference:

https://mumbai.polygonscan.com/tx/0xd347cf009bdfbc42871aeda3ee75b4091cdf5b95cb6376088e10858140b4b683

Hope it helps you!!!

4
  • Fantastic and thanks you so much, I will make use of this for my sample project, what i have learnt here is that all function has to work on scan before you can be able to call the programaticlay like using js to call them? secondly, is there any need to add this code or the gas fee will automatically goes into the contract? function withdrawGasFee() external onlyOwner { uint256 balance = address(this).balance; require(balance >= gasFee, "Insufficient balance"); payable(owner).transfer(gasFee); emit Withdrawal(owner, gasFee); }
    – Hallenjay
    Dec 25, 2023 at 15:13
  • But this your contract cannot be verified if deployed through remix?what could be the reason? I specified same 8. 19 version compiler for both my contact n compiler but same error. I m heading to hardhat to try it out though
    – Hallenjay
    Dec 25, 2023 at 15:52
  • Hi, hope it helps you. Yes, basically the good flow is to test in scan first, then it will work absolutely right in the JS code. For the verified problem, if you use Remix, you should make sure the version compile and compiler are the same. However, I would suggest you move to hardhat. You can verify SC really easy by a command line (refer to this hardhat.org/hardhat-runner/docs/guides/verifying). Finally, if your question has been well answered, please mark the answer as done to help other new commers to Web3 :D. Great to help.
    – tqdpham96
    Dec 25, 2023 at 18:16
  • Thanks, the code works fine on scan but i am running into pending transanction and sometime internal Rpc error, I will post my code down using the add comment so as i can use the code formatter
    – Hallenjay
    Dec 27, 2023 at 12:57
0
I get pending transanction and internal rpc error , this is myconnection to the binance testnet.

  document.addEventListener("DOMContentLoaded", async () => {
  let web3;
  let accounts;

  const initWeb3 = async () => {
    try {
      // Use the appropriate provider URL for the BSC network
      web3 = new Web3("https://data-seed-prebsc-1-s1.binance.org:8545/");

      web3.setProvider(window.ethereum);
      // Request account access
      accounts = await window.ethereum.request({
        method: "eth_requestAccounts",
      });
      updateConnectButtonText(); // Update button text on wallet connect
    } catch (error) {
      console.log("Error initializing Web3:", error);
    }
  };

//Increased gas too.

 
const receipt = await airdropContract.methods
          .claim() // Replace _GmcEarn and _gasFee with actual values
          .send({ from: accounts[0], gas: 2000000 });
        console.log(receipt);

    
1
  • changed the rpc endpoint and the error still the same but code work fine on bsc testnet scan
    – Hallenjay
    Dec 27, 2023 at 13:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.