0

I'm trying to transfer balance from one account to another, but whenever I try I get the following feedback...

Error: Returned error: VM Exception while processing transaction: revert ERC20: transfer amount exceeds allowance -- Reason given: ERC20: transfer amount exceeds allowance.

I'm trying to do this action via frontend (solidity test unit).

Below I put my files.

My file test.js

contract("Token721", (accounts) => {    
    let [alice, bob, cain, dan] = accounts;
    let contractInstance;
    beforeEach(async () => {
        coinInstance = await TokenCoin.deployed();                   
        contractInstance = await Token721.deployed();              
    });
describe("deploy Heroes", async () => {
    it("transfer founds from alice to bob", async () => {
        await coinInstance.transfer(bob, web3.utils.toWei("550", "ether"));
        let totalBob  = await coinInstance.balanceOf(bob);

        assert.equal(web3.utils.fromWei(totalBob.toString()), "550");
    })
    it("invoke a new hero", async () => {
        let totalBob  = await coinInstance.balanceOf(bob);
        console.log("TOTAL BOB "+web3.utils.fromWei(totalBob.toString()));

       const hero = await contractInstance.invokeRandomHero(bob, 
            'https://myurl.com/heroes/8356281049284737', cain, {from: bob, gas: 3000000});
        // const uri = await hero.tokenURI();        

        totalBob  = await coinInstance.balanceOf(bob);
        console.log("TOTAL BOB "+web3.utils.fromWei(totalBob.toString()));

        let totalCain  = await coinInstance.balanceOf(bob);
        console.log("TOTAL CAIN "+web3.utils.fromWei(totalCain.toString()));
    });
    xit("total heroes created is equals 1", async () => {
        const total = await contractInstance.totalHeroes();
        assert.equal(total.toString(), "1");
    });
});

})

My file ERC721.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract Token721 is Ownable, ERC721URIStorage { using Counters for Counters.Counter; Counters.Counter private _tokenIds;

//event para novos hero invocados event CreatedNewHero(uint heroId, string uri); //TEST COIN address coin; uint amountInvoke = 300;

constructor(address _coin) ERC721("Token721", "SAKH") { coin = _coin; }

function setCoin(address _coin) public{ coin = _coin; }

function invokeRandomHero(address _player, string memory _tokenURI, address _recepient) public returns (uint){ //CHECK IF EXISTS COINS IERC20 tokenA = IERC20(coin); uint _total = tokenA.balanceOf(_player);

if(_total &lt; amountInvoke)
  revert(&quot;No Founds&quot;);

tokenA.transferFrom(_player, _recepient, 300);

_tokenIds.increment();

uint256 newHeroId = _tokenIds.current();
_mint(_player, newHeroId);
_setTokenURI(newHeroId, _tokenURI);

// emit CreatedNewHero(newHeroId, _tokenURI); 

return newHeroId;       

}

function totalHeroes() public view returns(uint){ return _tokenIds.current(); }

}

Crazy
  • 161
  • 1
  • 7

1 Answers1

0

Asumming that the TokenCoin contract is an ERC20 you need to call approve before attempting a transfer. and also you need to run the TokenCoin contract as alice to with the connect method.

It will look like this:

it("transfer founds from alice to bob", async () => {
        await coinInstance.connect(alice).approve(bob, web3.utils.toWei("550", "ether"));
        await coinInstance.connect(alice).transfer(bob, web3.utils.toWei("550", "ether"));
        let totalBob  = await coinInstance.balanceOf(bob);
    assert.equal(web3.utils.fromWei(totalBob.toString()), &quot;550&quot;);
})

Julissa DC
  • 1,888
  • 1
  • 8
  • 21
  • Thanks for the answer.. I would like to use transfer inside the invokeRandomHero method, would it be possible? Or not? – Crazy Nov 01 '21 at 14:31
  • You can, as long as you do the approve first outside of the function – Julissa DC Nov 01 '21 at 17:10
  • I tried this:
    await coinInstance.connect(alice).approve(cain, web3.utils.toWei("550", "ether"), {from: bob})
                const hero = await contractInstance.invokeRandomHero(bob, 
                    'https://myurl.com/heroes/8356281049284737', cain, {from: bob, gas: 3000000});
    

    but I'm having the error saying: TypeError: coinInstance.connect is not a function

    – Crazy Nov 02 '21 at 07:32