Reputation: 35
I need heed help how can I solve this problem? The smart contract is deployable on mumbai testnet but when I tried to deploy it on polygon I got this (on the title above) error. Anyone know how can I solve this so I can deploy it on polygon mainnet on remix? Anyone knows how to fix the 'contract creation code storage out of gas' error?
Here is the code of my contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.2/contracts/token/ERC721/ERC721.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.2/contracts/token/ERC20/IERC20.sol";
contract TestNFT is ERC721 {
using SafeMath for uint256;
address public owner;
string public _tokenURI;
uint256 private _tokenIdTracker;
uint256 private maxSupply = 10000;
uint8 public decimal;
address payable[] private recipients;
uint[] private percentages;
// nftHolders & nftMinteres mapping
mapping(address => bool) private nftHolders;
// Mint Fee
uint256 private mintFee;
// Royalty after mint
uint256 private royaltyFee;
// Recipients and percentages events
event RecipientsUpdated(address payable[] recipients, uint[] percentages);
// Nft events
event NftWithburnt(address currentOwner, uint256 tokenId);
event NftWithdrawn(
address indexed recipient,
uint256 tokenId,
address indexed nftContract
);
event NftMinted(address indexed recipient, uint256 nftAmount);
// Eth events
event Deposit(address indexed sender, uint256 amount);
event Forwarded(uint256 totalAmount, uint256[] amounts);
constructor() ERC721("Project", "X") {
decimal = 0;
owner = payable(msg.sender);
mintFee = 0.01 ether;
royaltyFee = 5; //default 5%.
recipients.push(payable(0x22AbA4c94E703e280A96713c26a1c1872AB45D9e));
percentages.push(20);
recipients.push(payable(0xCAeaA9D2DffF37c240bafC215608752c9C125B42));
percentages.push(5);
recipients.push(payable(0xe1C87F43c12a7B43Bee853e66F0BCB3dd75d9E95));
percentages.push(55);
recipients.push(payable(0x38d5a7EF9DB64D05A47c82C5E42bB45A7C82B457));
percentages.push(20);
require(
percentages.length == recipients.length,
"Recipients and percentages length mismatch"
);
require(
percentages.length <= 4,
"Cannot specify more than 4 recipients"
);
uint totalPercentage;
for (uint i = 0; i < recipients.length; i++) {
require(
recipients[i] != address(0),
"Recipient address cannot be zero"
);
require(percentages[i] > 0, "Percentage must be greater than zero");
totalPercentage += percentages[i];
}
require(totalPercentage == 100, "Percentages must add up to 100");
}
// Modifier to onlyOwner
modifier onlyOwner() {
require(
msg.sender == owner,
"Only the contract owner can call this function."
);
_;
}
// Get total nftSupply
function totalSupply() public view returns (uint256) {
return _tokenIdTracker;
}
// Get MaxSupply
function getMaxSupply() public view returns (uint256) {
return maxSupply;
}
// Check the current tokenURI
function _baseURI() internal view override returns (string memory) {
return _tokenURI;
}
// TokenURI updatable
function setTokenURI(string memory tokenURI) public onlyOwner {
_tokenURI = tokenURI;
}
// Updating royalty fee
function updateRoyaltyFee(uint256 newRoyaltyFee) external onlyOwner {
require(newRoyaltyFee <= 10); //
royaltyFee = newRoyaltyFee;
}
function UpdateMintFee(uint256 newMintFee) external onlyOwner {
mintFee = newMintFee;
}
function getMintFee() public view returns (uint256) {
return mintFee;
}
// Update maxSupply
function updateMaxSupply(uint256 newMaxSupply) external onlyOwner {
maxSupply = newMaxSupply;
}
//View contract balance
function getETHBalance() public view returns (uint256) {
return address(this).balance;
}
function getStakingAddress() public view returns (address payable) {
require(recipients.length >= 0, "Recipient does not exist");
return recipients[0];
}
function getCharityAddress() public view returns (address payable) {
require(recipients.length >= 1, "Recipient does not exist");
return recipients[1];
}
function getMarketingAddress() public view returns (address payable) {
require(recipients.length >= 2, "Recipient does not exist");
return recipients[2];
}
function getLiquidityAddress() public view returns (address payable) {
require(recipients.length >= 3, "Recipient does not exist");
return recipients[3];
}
// Receive fallback function
receive() external payable {
if (msg.value > 0) {
distributeRoyalties();
}
}
// Deposit or transfer Eth to contract
function deposit() public payable {
require(
msg.value > 0,
"deposit(ETH): input an amount, zero deposit is not allowed. "
);
distributeRoyalties();
emit Deposit(msg.sender, msg.value);
}
// Forward Eth to recipients
function distributeRoyalties() internal {
require(
msg.value > 0,
"distributeRoyalties: amount is too low for distribution."
);
uint256 balance = address(this).balance;
uint256[] memory amounts = new uint256[](recipients.length);
for (uint i = 0; i < recipients.length; i++) {
amounts[i] = (balance * percentages[i]) / 100;
require(amounts[i] > 0, "Amount is too low");
(bool sent, ) = recipients[i].call{value: amounts[i]}("");
require(sent, "Failed to send Ether to recipient");
}
emit Forwarded(balance, amounts);
}
//Function to mint new NFT
function mint(uint256 nftAmount) public payable {
require(nftAmount > 0, "mint: zero nftAmount not allowed.");
require(
_tokenIdTracker.add(nftAmount) <= maxSupply,
"mint: Minting have reached the MaxSupply."
);
//Calculate the minting fee (Eth)
uint256 fee = nftAmount.mul(mintFee); // default: 10 Matic fee per NFT minted
// Check if the sender is the contract owner
if (msg.sender != owner) {
require(msg.value >= fee, "mint: Incorrect mintFee amount");
distributeRoyalties(); //Transfer the fee to the contract address
}
// Mint the NFT and transfer it to the minter
for (uint256 i = 0; i < nftAmount; i++) {
uint256 tokenId = _tokenIdTracker;
_safeMint(msg.sender, tokenId);
_tokenIdTracker = _tokenIdTracker.add(1);
}
// Add the 'msg.sender' address to the tokenHolders mapping if it doesn't already exist
if (balanceOf(_msgSender()) > 0) {
nftHolders[_msgSender()] = true;
} else if (balanceOf(_msgSender()) == 0) {
nftHolders[_msgSender()] = false;
}
// Refund excess ETH back to the user
if (msg.value > fee) {
address payable sender = payable(msg.sender);
sender.transfer(msg.value.sub(fee));
}
emit NftMinted(msg.sender, nftAmount);
}
// any users can burn their token
function burn(uint256 tokenId) public {
require(
_isApprovedOrOwner(_msgSender(), tokenId),
"burn: caller is not owner nor approved"
);
_burn(tokenId);
_tokenIdTracker--;
// Remove the 'msg.sender' address from the tokenHolders mapping if it no longer holds any tokens
if (balanceOf(_msgSender()) == 0) {
nftHolders[_msgSender()] = false;
} else if (balanceOf(_msgSender()) > 0) {
nftHolders[_msgSender()] = true;
}
emit NftWithburnt(_msgSender(), tokenId);
}
// Override NFTtransfers when contract is paused
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
require(
_isApprovedOrOwner(_msgSender(), tokenId),
"ERC721: caller is not token owner or approved"
);
_transfer(from, to, tokenId);
}
// Override NFTtransfers when contract is paused
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
require(
_isApprovedOrOwner(_msgSender(), tokenId),
"ERC721: caller is not token owner or approved"
);
_transfer(from, to, tokenId);
}
// Transfer with data(public)
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory data
) public virtual override {
require(
_isApprovedOrOwner(_msgSender(), tokenId),
"ERC721: caller is not token owner or approved"
);
_safeTransfer(from, to, tokenId, data);
}
// Transfer with data(internal)
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory data
) internal virtual override {
_transfer(from, to, tokenId);
if (data.length > 0) {
require(
_checkOnERC721Received(from, to, tokenId, data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
}
//check the reciever
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
// Check the reciever and data
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory data
) internal virtual override returns (bool) {
if (isContract(to)) {
try
IERC721Receiver(to).onERC721Received(
_msgSender(),
from,
tokenId,
data
)
returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert(
"ERC721: transfer to non ERC721Receiver implementer"
);
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
// Override the ERC721 _transfer function to add tracking
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
require(
_isApprovedOrOwner(_msgSender(), tokenId),
"_transfer(): caller is not owner nor approved"
);
require(
ERC721.ownerOf(tokenId) == from,
"_transfer(): transfer from incorrect owner"
);
require(
to != address(0),
"_transfer(): transfer to the zero address not allowed"
);
// Add the 'to' address to the tokenHolders mapping if it doesn't already exist
if (balanceOf(to) > 0) {
nftHolders[to] = true;
} else if (balanceOf(to) == 0) {
nftHolders[to] = false;
}
// Remove the 'from' address from the tokenHolders mapping if it no longer holds any tokens
if (balanceOf(from) == 0) {
nftHolders[from] = false;
} else if (balanceOf(from) > 0) {
nftHolders[from] = true;
}
super._transfer(from, to, tokenId);
}
// Get the total number of unique token holders
function totalHolders() public view returns (uint256) {
uint256 count = 0;
// Create an array of all the keys in the nftHolders mapping using the getKeys() function
address[] memory keys = new address[](totalSupply());
// Iterate over all token IDs and add the holder's address to the keys array if it hasn't already been added
for (uint256 i = 0; i < totalSupply(); i++) {
address holder = ownerOf(i);
bool found = false;
for (uint256 j = 0; j < keys.length; j++) {
if (keys[j] == holder) {
found = true;
break;
}
}
if (!found) {
keys[count] = holder;
count++;
}
}
return count;
}
// Send ERC20 token from balance to all royalty recipients
function distributeERC20(address tokenAddress) external onlyOwner {
require(
msg.sender == owner,
"Only the owner can withdraw ERC20 tokens"
);
require(recipients.length > 0, "No recipients specified");
require(
percentages.length == recipients.length,
"Recipients and percentages length mismatch"
);
require(
percentages.length <= 4,
"Cannot specify more than 4 recipients"
);
// Get ERC20 token balance in contract
IERC20 token = IERC20(tokenAddress);
uint256 tokenBalance = token.balanceOf(address(this));
require(tokenBalance > 0, "Contract has no tokens to withdraw");
uint256[] memory amounts = new uint256[](recipients.length);
uint256 totalPercentage;
for (uint i = 0; i < recipients.length; i++) {
totalPercentage += percentages[i];
}
for (uint i = 0; i < recipients.length; i++) {
amounts[i] = (tokenBalance * percentages[i]) / totalPercentage;
require(amounts[i] > 0, "Amount is too low");
token.transfer(recipients[i], amounts[i]);
}
emit Forwarded(tokenBalance, amounts);
}
// Function to receive NFT
function onERC721Received(
address,
address,
uint256,
bytes memory
) public virtual returns (bytes4) {
return this.onERC721Received.selector;
}
// Forward Eth to recipients
function callDistribution() external payable onlyOwner {
uint256 balance = address(this).balance;
uint256[] memory amounts = new uint256[](recipients.length);
for (uint i = 0; i < recipients.length; i++) {
amounts[i] = (balance * percentages[i]) / 100;
require(
amounts[i] > 0,
"callDistribution: amount is too low for distribution."
);
(bool sent, ) = recipients[i].call{value: amounts[i]}("");
require(sent, "Failed to send Ether to recipient");
}
emit Forwarded(balance, amounts);
}
// Function to rescue NFT
function rescueNft(
address nftContract,
uint256 tokenId
) external onlyOwner {
require(_exists(tokenId), "ERC721Metadata: nonexistent token");
require(
ownerOf(tokenId) == address(this),
"The NFT is not in this contract's balance"
);
IERC721(nftContract).safeTransferFrom(
address(this),
msg.sender,
tokenId
);
emit NftWithdrawn(msg.sender, tokenId, nftContract);
}
} ```
Upvotes: -1
Views: 2177
Reputation: 329
Short answer - you have an insufficient amount of Matic in your wallet to deploy.
Long answer - I will address both your error message & the contract code.
The Error Message
This error occurs when trying to deploy a new contract to the network with insufficient gas, therefore it fails.
Gas is the fee required to execute a transaction/ deploy contract on the blockchain. The gas is paid with the native coin of the network. For Ethereum, it's ETH, for Polygon & Mumbai(polygon testnet) it's Matic.
So to deploy your contract on Polygon you need to:
If you want to learn more about the gas standard you can read the official EIP-1559 regarding the newest gas payment standard.
The remix deploy panel is supposed to look like this:
I've tested and successfully deployed the contract to Polygon
The Contract Code
The contract code should be minimized and simplified. You are inheriting the ERC721 contract but you also manually added the ERC721 to your contract, for example, the _checkOnERC721Received function. And by that increasing your contract byte size. If you will continue to add code to the current state of your contract you will receive another error : Contract code size exceeds 24576 bytes (a limit introduced in Spurious Dragon). Meaning your contract is too large for deploying.
I've tried to use your code in remix but some of your imports don't exist so I've replaced them with the updated version.
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.8/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
Upvotes: 0