Trying to send a fee (in ether) while minting an NFT
Environment
“@openzeppelin/contracts-upgradeable”: “^4.0.0”,
“truffle”: “^5.3.1”
Details
Implemented following code:
function sendMintingFee() internal {
require(!locked, "Reentrant detected!");
locked = true;
uint256 feevalue = _calculateMintingFee();
(bool success, bytes memory transactionBytes) = FeeAddress.call{value: feevalue}("");
require(success, "Transfer failed.");
locked = false;
emit FeePaid(msg.sender, feevalue);
}
function mintWithFee(
address _to,
Fee[] memory _fees,
AttributesStruct[] memory _attributes
) external {
require(
FeeAddress != address(0),
"minting Fee Address not set"
);
if (FeeMultiplier > 0) {
sendMintingFee();
}
mint(_to, _fees, _attributes);
}
/**
* @dev set the wallet address where fees will be collected
*/
function setFeeAddress(address payable _FeeAddress)
public
{
require(
hasRole(DEFAULT_ADMIN_ROLE, _msgSender()),
"Caller must have admin role to set minting fee address"
);
FeeAddress = _FeeAddress;
emit FeeAddressChanged(FeeAddress);
}
/**
* @dev sets the transfer fee multiplier
*/
function setFeeMultiplier(uint256 _FeeMultiplier)
public
{
require(
hasRole(DEFAULT_ADMIN_ROLE, _msgSender()),
"Caller must have admin role to set minting fee percent"
);
FeeMultiplier = _FeeMultiplier;
emit FeeMultiplierChanged(FeeMultiplier);
}
/**
* @dev sets the transfer fee multiplier
*/
function setMintFee(uint256 _MintingFee) public {
require(
hasRole(DEFAULT_ADMIN_ROLE, _msgSender()),
"Caller must have admin role to set minting fee percent"
);
MintingFee = _MintingFee;
emit MintFeeChanged(MintingFee);
}
function _calculateMintingFee() internal view returns (uint256) {
return MintingFee * FeeMultiplier;
}
The trasnfer never succeeds and bool success = false
as expeced the following error is thrown:
Error: Returned error: VM Exception while processing transaction: revert Transfer failed. -- Reason given: Transfer failed..
How do solve the issue that the user invoking the contract must pay a fee for minting process?
Must the contract be funded?
Method can be tested with this test function:
it.only("mint with fee", async function () {
const minter = accounts[1]
const feeAddress = accounts[2]
await this.NFT.setFeeAddress(feeAddress)
await this.NFT.setFeeMultiplier(1)
await this.NFT.setMintFee("100000000000000000")
console.log("FeeMultiplier: ",await this.NFT.FeeMultiplier)
console.log("MintingFee: ",await this.NFT.MintingFee)
console.log("FeeAddress: ",await this.NFT.FeeAddress)
const receipt = await this.NFT.mintWithFee(minter, [{ recipient: minter, value: 100 }], [{ key: "bar", value: "1234" }]);
const tokenId = new BN(parseInt(await this.NFT.getCurrentCounter()) - 1)
let balance = (await this.NFT.balanceOf(feeAddress)).toString();
assert.equal(balance, 100000000000000000);
});
Code to reproduce
https://github.com/selimerunkut/nft_troubleshoot