Create a survey app that reward with an ERC20 token

Hello,

I am creating a test app that reward users that complete a survey with an ERC20 token. I already have the ERC20 smart contract with a token supply of 5000000 token and the survey app in react and javascript. I want to link the two together so when a user click on submit, they receive 10 token from the initial wallet address.

Thank you very much.

1 Like

Congrats for your project. Great idea. pls send me the Link of your App. Wishing . .

Hello,

I just need help to create the reward function in solidity. This is what i did, but it is not working.

mapping(uint => Reward) public rewards;

</>
struct Reward{
uint id;
uint tokenReward;
address payable author;
}

event  UserRewarded(
    uint id,
    string content,
    uint tokenReward,
    address payable author
);

constructor() ERC20("MyTestToken", "MTT") {
    _mint(msg.sender, 7000000000000000000000000);
}

function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
    _transfer(_msgSender(), recipient, amount);
    return true;
}

function rewardUser(uint _id) public payable {
   //Make sure Id is valid
   require(_id > 0);
   // Fetch reward
   Reward memory _reward = rewards[_id];
   // Fetch the user
   address payable _user = _reward.id;
   //Pay user by sending them MTT
   address(Reward.author).transfer(msg.value);
   // Increment the reward amount
   _reward.tokenReward = _reward.tokenReward + msg.value;
   // Trigger event
   emit UserRewarded(_id, _reward.content, _reward.tokenReward, Reward._author);

    //   transfer(recipient, 10 * 10^18);
    //  address(recipient).transfer(msg.value);
}

}
</>

thank you

Hey, welcome! :wave:

It seems like your target is to reward some token, but for your code just like above, it means you want to reward ETH. I think it should be token.transfer(to, amount)

1 Like

Hi Skyge,

Yes i want to reward with the token that i created. So it is just a simple transfer function right? I don't need all of this?

Thank you.

Up to you, I just mean, you should use token.transfer(to, amount) to transfer token, the code you wrote above address(Reward.author).transfer(msg.value); is transferring ETH.

1 Like

Thank you very much, so my code should look like this.

contract MyTestToken is ERC20, Ownable {
    using SafeMath for uint256;

    mapping(address => uint256) private _balances;

    constructor() ERC20("MYTestToken", "MTT") {
        _mint(msg.sender, 7000000000000000000000000);
    }

    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
        }

function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
        token.transfer(to,amount);
    }

}

Okay, maybe I misled you. It should be YOUR_TOKEN.transfer(RECIPIENT_ADDRESS, TRANSFER_AMOUNT), for example, Alice should get 10 DAI, so it should be DAI_CONTRACT.transfer(ALICE_ADDRESS, 10e18)

1 Like

Thank you,I think that's the easiest way. I fixed it. But now how do i implement it in web3 please?

await MyTestToken.methods
      .transfer(this.state.account, 707e18)
      .send({ from: contractAddress }, function (error, transactionHash) {
        console.log(transactionHash);
      });

No, contract can not send transactions automatically, there must be someone(A user or another contract) triggers it.

Maybe your function should be:

function rewardUser(uint _id) public {
   //Make sure Id is valid
   require(_id > 0);
   // Fetch reward
   Reward memory _reward = rewards[_id];
   // Fetch the user
   address payable _user = _reward.id;
   //Pay user by sending them MTT
   MTT.transfer(msg.sender, EXPECTED_AMOUNT); // <<<<<<-------------------here
   // Increment the reward amount
   _reward.tokenReward = _reward.tokenReward + msg.value;
   // Trigger event
   emit UserRewarded(_id, _reward.content, _reward.tokenReward, Reward._author);

    //   transfer(recipient, 10 * 10^18);
    //  address(recipient).transfer(msg.value);
}

Hello, I tried what you did but didn't manage to do it. I think the easir thing to achieve what i want is to implement an airdrop function or contract.

function getAirdrop() public {
    token.transfer(msg.sender, 100000000000000000000); //18 decimals token
  }

Do i need it to put in a different file or can i put it in the same contract as the token creation?

Thank you very much

Up to you.

And I think at least you should have a flag to define whether the caller account has claimed, so do you expect the user can claim all the time?

Yes since it is just a test app

This is what my code look like. But i get an error when i call the function in my JavaScript.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.1;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";


contract MyTestToken is ERC20, Ownable {

    mapping(address => uint256) private _balances;

  event Airdropped(address indexed from, address indexed to, uint256 tokens);  

   // address owner = msg.sender;

    constructor() ERC20("MyTestToken", "MTT") {
        _mint(msg.sender, 7000000 * 10 ** decimals());
    
    }
    
    function getAirdrop(address from) public payable {
        MyTestToken token = MyTestToken(0x33B245F34a4708F69e4690cf31D42aBA76278296);
    token.transfer(msg.sender, msg.value); //18 decimals token 60000000000000000000
    emit Airdropped(from, msg.sender, 600000000000000000000);
  }
    
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
        }
    
}

Pretty crazy I'm building an identical app for a school project ha! Came here looking for the exact same information. Great!

1 Like

So for your function getAirdrop(), you mean you want the users to call this function with Ether, just like uses 1 Ether to get 1 airdrop token, right?

I think it looks like ok, just ensure your contract have enough token to transfer out, and when you call this function with Ether, I think it should be YOUR_CONTRACT.methods.getAirdrop(AN_ADDRESS, {value:ETHER_AMOUNT}) (I use web3.js, if you use other ways, maybe there will be some differences)