dadmfers is the first mfers derivative project, and they just recently released BackgroundMfers, a series of dadmfers inspired banner images. This required a new contract, with some additional complexity because of the number of mint options. The contract provides 5 separate minting functions for getting your background mfers NFTs:
- Public mint for anyone
- Mfer mint, for anyone that has mfers, at a reduced price
- Whitelist mint, free anyone on their list
- Dadmfers v1 mint for free
- Dadmfers v2 mint for free
Why some many minting options? It does add complexity, but there are good reasons, such as more favorable pricing for mfers holders, or free mints for dadmfers holders, while still allowing anyone to participate with the public option. There are two dadmfers options, v1 & v2, because the original v1 contract for dadmfers had very high gas fees. This turned a lot of people away, but the team quickly responded with a much more gas optimized contract. However, since the original contract had already been deployed, a new one was needed, because smart contracts cannot be upgraded once deployed (unless you use a proxy contract). So a v2 gas optimized contract was deployed, and everyone that minted on v1 was given free airdrops for v2. Ok, enough backstory, lets look at the background mfers contract code, available on etherscan.
function mintPublic(uint256 _mintAmount) public payable mintCompliance(_mintAmount) {
require(msg.value >= publicCost * _mintAmount, "Not enough eth sent!");
require(_mintAmount < maxMintAmountPlusOne, "trying to mint too many!");
_mintLoop(msg.sender, _mintAmount);
}
Public Mint
This mintPublic
function is very simple at first glance, but has a lot of dependencies to go into. It takes a _mintAmount
, checks it with mintCompliance
, then does 2 more checks before minting. Let’s look at mintCompliance
since it’s also used by the other mint functions.
mintCompliance
modifier mintCompliance(uint256 _mintAmount) {
require(_mintAmount > 0, "Invalid mint amount!");
require(supply.current() + _mintAmount < maxSupplyPlusOne, "Max supply exceeded!");
require (saleIsActive, "Public sale inactive");
_;
}
Here we can see 3 requirements:
_mintAmount
must be a positive integer- You can’t mint more than is available
- Minting must be active
These have some implications:
- There is a max supply
- Minting can be de-activated or re-activated
The max supply is defined by uint256 public maxSupplyPlusOne = 10_001
at the top of the contract. However, there’s also the following function at the bottom of the contract, which allows the contract owner to lower the supply.
function lowerSupply(uint256 newSupply) public onlyOwner {
if (newSupply < maxSupplyPlusOne) {
maxSupplyPlusOne = newSupply;
}
}
Supply lowering can be a good thing to do if the collection doesn’t mint out in a certain period of time. By lowering the supply, you can preserve the current rarities and NFT values, potentially making the existing NFTs more valuable. Dadmfers v2 also lowered the supply after some time passed and it hadn’t sold out.
The contract owner can also disable or enable minting with the setSale
function, which sets the salesIsActive
variable.
function setSale(bool newState) public onlyOwner {
saleIsActive = newState;
}
_mintLoop
function _mintLoop(address _receiver, uint256 _mintAmount) internal {
for (uint256 i = 0; i < _mintAmount; i++) {
supply.increment();
_safeMint(_receiver, supply.current());
}
}
This function is called with msg.sender
(i.e. your wallet address) and the amount you want to mint. It does a simple for loop to increment the used supply, then mints a token. _safeMint
is a standard function in OpenZeppelin’s ERC721, so we won’t go into that here.

Mfers Mint
function mintWithMfers(uint256 [] memory nftIds) public payable mintCompliance(nftIds.length) {
require(msg.value >= mferCost * nftIds.length, "Not enough eth sent!");
for (uint256 i = 0; i < nftIds.length; i++) {
require(mfersContract.ownerOf(nftIds[i]) == msg.sender, "You must own all the mfers!");
require(usedMferIds[nftIds[i]] == false, "One of the mfer IDs has already been used!");
supply.increment();
_safeMint(msg.sender, supply.current());
usedMferIds[nftIds[i]] = true;
}
}
For this minting function, it expects a list of mfers tokens. These come from the selectors on the website. After checking mintCompliance
and amount of eth sent, it loops through the tokens. If any token is not owned by you, or has already been used to mint, this function will fail. But if you are the owner of all the mfers tokens, it will do a mint for each one, and record the mfers token as used.
If you’re wondering why you have to check token ownership in the contract, when it’s already done on the website, that’s because smart contracts can be called directly, without going through the website. For example, you could go to the Write Contract section on etherscan, find the mintWithMfers
function, and enter values directly there. This is something that all smart contract developers need to be aware of – you can’t assume people will only interact with the contract through your website.
Let’s dig into require(mfersContract.ownerOf(nftIds[i]) == msg.sender
a bit more. mfersContract
is defined at the top of the contract as nftInterface mfersContract = nftInterface(0x79FCDEF22feeD20eDDacbB2587640e45491b757f);
.
So what’s nftInterface
?
interface nftInterface {
function ownerOf(uint256 tokenId) external view returns (address owner);
function balanceOf(address owner) external view returns (uint256);
function totalSupply() external view returns (uint256);
}
This is defined outside the contract, and provides a way to interact with another contract, by defining some functions that the contract should support. So mfersContract
is an interface to the smart contract behind mfers (which you can see at this address on etherscan: 0x79FCDEF22feeD20eDDacbB2587640e45491b757f), and the background mfers contract is calling the mfers contract to check token ownership. These 3 functions (ownerOf
, balanceOf
, and totalSupply
) are all standard ERC721 functions.

Dadmfer v1 & v2 Mint
function mintWithDadmfersV1(uint256 [] memory nftIds) public mintCompliance(nftIds.length) {
for (uint256 i = 0; i < nftIds.length; i++) {
require(dadmfersV1Contract.ownerOf(nftIds[i]) == msg.sender, "You must own all the dadmfer V1s!");
require(usedV1Ids[nftIds[i]] == false, "One of the dadmfer IDs has already been used!");
supply.increment();
_safeMint(msg.sender, supply.current());
usedV1Ids[nftIds[i]] = true;
}
}
function mintWithDadmfersV2(uint256 [] memory nftIds) public mintCompliance(nftIds.length) {
for (uint256 i = 0; i < nftIds.length; i++) {
require(dadmfersV2Contract.ownerOf(nftIds[i]) == msg.sender, "You must own all the dadmfer V2s!");
require(usedV2Ids[nftIds[i]] == false, "One of the dadmfer IDs has already been used!");
supply.increment();
_safeMint(msg.sender, supply.current());
usedV2Ids[nftIds[i]] = true;
}
}
Both of these functions are very similar to each other and the mintWithMfers
function. The main difference is dadmfersV1Contract
vs dadmfersV2Contract
. Just like with mfersContract
, these are interfaces to the dadmfers contracts. The difference with mintWithMfers
is that the initial requirement check for eth sent is gone, because these are free mints.

Slither Analysis
Slither is a python tool for static analysis of Solidity contracts. You can use it to get a quick summary of the contract code, and then look for any deeper issues.
$ slither 0xc0a5393aA132DE6a66369Fe6e490cAc768991Ea5 --print human-summary

This fits with what we’ve seen above, the BackgroundMfers contract is complex code for minting ERC721 NFTs. The 11 medium issues are very technical to describe, but reduce down to “not a problem”. The contract does not implement onERC721Received
, so there’s no real reentrency concerns, and the other issues look more like syntax & style choices in foreignNftsForWallet
, which is a read-only function that is not used for minting.
Conclusion
While somewhat complicated, the background mfers contract looks quite safe for minting, and appears to be gas optimized. It allows batch minting to receive multiple tokens, which usually saves in gas fees. And there’s nothing in the minting functions that seems unnecessary. If you have any questions about the project, you can ask in the dadmfers discord; everyone is very friendly. As of publish time, they have not revealed the images yet, but when they do, you’ll be able to see the background mfers on looksrare or opensea.
I didn’t cover the whitelistMint
because most people won’t be using that one. There’s also a complicated looking function foreignNftsForWallet
that returns all the token IDs owned by a wallet, for a given contract. You can test this for yourself in the Read Contract section on etherscan, if you know a wallet address that owns one or more of mfers, dadmfers v1 or v2. For example, the address 0x4873f1768e1833fa6fb720b183715c7f57ecf953
is the wallet of the contract creator, so if you enter that and input 1
, you can see it owns token 908 for dadmfers v2. Use input 0
for dadmfers v1 or input 2
for mfers.
