Hey guys, I have 2 contracts. The first one is the RoyaltiesToken.sol
where I mint "N" tokens ERC-20 to the sender account. The second one is the MyNFT.sol
which is a ERC-721 tokens where another account deploy it creating a new NFT. These are represented below:
RoyaltiesToken.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract RoyaltiesToken is ERC20 {
constructor() ERC20("My Royaltie token", "MRT") {
_mint(msg.sender, 200000 * 10**18);
}
}
MyNFT.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract MyNFT is ERC721 {
address public artist;
address public admin = 0x3E123Cb3a81E22f4DC4152ad8dBfc30D21984A7e;
address public txFeeTokenRoyaltie;
uint256 public txFeeAmountArtist;
uint256 public txFeeAmountPlatform;
string public tokenURI;
mapping(address => bool) public excludedList; // list manipulated by artist to set who need and who does not need to pay royalties
constructor(
address _txFeeTokenRoyaltie,
uint256 _txFeeAmountArtist,
uint256 _txFeeAmountPlatform,
string memory _tokenURI
) public ERC721("MyNFT", "NFT") {
artist = msg.sender;
txFeeTokenRoyaltie = _txFeeTokenRoyaltie;
txFeeAmountArtist = _txFeeAmountArtist;
txFeeAmountPlatform = _txFeeAmountPlatform;
tokenURI = _tokenURI;
_mint(artist, 0);
}
function setExcluded(address excluded, bool status) external {
require(msg.sender == artist, "Artist only");
excludedList[excluded] = status;
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public override {
require(
_isApprovedOrOwner(_msgSender(), tokenId),
"ERC721: transfer caller is not owner nor approved"
);
if (excludedList[from] == false) {
_payTxFeeArtist(from);
}
_payTxFeeAdmin(from);
_transfer(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public override {
safeTransferFrom(from, to, tokenId, "");
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public override {
require(
_isApprovedOrOwner(_msgSender(), tokenId),
"ERC721: transfer caller is not owner nor approved"
);
if (excludedList[from] == false) {
_payTxFeeArtist(from);
}
_payTxFeeAdmin(from);
_safeTransfer(from, to, tokenId, _data);
}
function _payTxFeeArtist(address from) internal {
IERC20 tokenArtist = IERC20(txFeeTokenRoyaltie);
tokenArtist.transferFrom(from, artist, txFeeAmountArtist);
}
function _payTxFeeAdmin(address from) internal {
IERC20 tokenAdmin = IERC20(txFeeTokenRoyaltie);
tokenAdmin.transferFrom(from, admin, txFeeAmountPlatform);
}
}
My problem is when I try to transferFrom
the NFT and pay royalties with the ERC-20. Below, you can check how I wrote my test.
Test.js
const RoyaltiesToken = artifacts.require("RoyaltiesToken");
const MyNFT = artifacts.require("MyNFT");
const assert = require("assert");
before(async () => {
royaltiesToken = await RoyaltiesToken.new();
});
contract("RoyaltiesToken and NFT Token", async (accounts) => {
const admin = accounts[0];
const artist = accounts[1];
const owner1 = accounts[2];
const owner2 = accounts[3];
let mynft;
let txFee = BigInt(10 ** 18);
let balanceAdmin;
let balanceArtist;
let balanceOwner1;
let balanceOwner2;
it("Admin should transfer RoyaltieTokens to artist, owner1 and owner2", async () => {
await royaltiesToken.transfer(artist, BigInt(500 * 10 ** 18));
await royaltiesToken.transfer(owner1, BigInt(500 * 10 ** 18));
await royaltiesToken.transfer(owner2, BigInt(500 * 10 ** 18));
balanceAdmin = await royaltiesToken.balanceOf(admin);
balanceArtist = await royaltiesToken.balanceOf(artist);
balanceOwner1 = await royaltiesToken.balanceOf(owner1);
balanceOwner2 = await royaltiesToken.balanceOf(owner2);
assert.equal(balanceAdmin.toString(), "198500000000000000000000");
assert.equal(balanceArtist.toString(), "500000000000000000000");
assert.equal(balanceOwner1.toString(), "500000000000000000000");
assert.equal(balanceOwner2.toString(), "500000000000000000000");
});
it("Artist should create an NFT contract", async () => {
mynft = await MyNFT.new(royaltiesToken.address, txFee, txFee, "test", {
from: artist,
});
let artist_address = await mynft.artist.call();
let ownerNFT = await mynft.ownerOf(0);
assert(ownerNFT, artist);
assert(artist_address, artist);
});
it("Artist should transfer NFT to owner1 and pay royalties", async () => {
await mynft.setExcluded(artist, true, { from: artist });
await royaltiesToken.approve(artist, txFee, { from: admin });
let allowance = await royaltiesToken.allowance(admin, artist);
assert.equal(allowance.toString(), "1000000000000000000");
**await mynft.transferFrom(artist, owner1, 0, { from: artist });**
let ownerNFT = await mynft.ownerOf(0);
assert(ownerNFT, owner1);
balanceAdmin = await royaltiesToken.balanceOf(admin);
balanceArtist = await royaltiesToken.balanceOf(artist);
balanceOwner1 = await royaltiesToken.balanceOf(owner1);
balanceOwner2 = await royaltiesToken.balanceOf(owner2);
assert.equal(balanceAdmin.toString(), "198600000000000000000000");
assert.equal(balanceArtist.toString(), "499000000000000000000");
assert.equal(balanceOwner1.toString(), "500000000000000000000");
assert.equal(balanceOwner2.toString(), "500000000000000000000");
});
});
I got the error: Error: Returned error: VM Exception while processing transaction: revert ERC20: transfer amount exceeds allowance -- Reason given: ERC20: transfer amount exceeds allowance.
I also marked with * the error in Test.js to make the observation easier.
Someone can help me how to fix it?