We are working on a charity NFT, and we want to gate minting to those who have ALREADY donated to the charity by sending ETH to the charity wallet.

This makes things cleaner for tax write off purposes for the minter vs. just doing a rev share to the charity on the contract.

Implementation Idea #1: Offchain admin signature

The way we are thinking about implementing it is by querying off chain whether the minter address has donated, and if they have sign a custom message with an "admin wallet" private key for their address that gives them mint access (after ECDSA signature verification on chain).

Implementation Idea #2: Direct on chain verification??

The downside of implementation #1 is it relies on a centralized server and admin private key to query the chain and gate access.

I was wondering if it might be possible to have the minter submit their donation transaction hash or some sort of merkle proof maybe? and verify directly on chain that the transaction was valid and mined?

  • Did people already donate to your wallet? Because if no, you can create a smart contract that will log whoever sent it ether. But I'm guessing you already have donations done to an EOA account. Jul 23, 2022 at 1:56
  • 1
    We don't already have donations, and this is definitely an option. I suppose the only downside is the gas cost for storage overhead on logging the donors. Jul 23, 2022 at 21:16

1 Answer 1


Another option is to add some logic to your NFT's smart contract to store the addresses that have donated and only allow them to mint an NFT.

contract CharityNFT is ERC721 {

    mapping(address => uint256) public addressToAmountDonated;
    uint256 private NFTCounter;

    constructor () ERC721("charityNFT", "NFT") public {
        NFTCounter = 0;

    function mintNFT() public returns(uint256) {
        require(addressToAmountDonated[msg.sender] > 0, "Address has not donated");
        _safeMint(msg.sender, NFTCounter);
        NFTCounter = NFTCounter + 1;
        return NFTCounter;

You would need to add a donate() (and probably a receive()) function to allow users to send funds and track the amounts with the addressToAmountDonated mapping, as well as a withdraw() function that only allows your address to withdraw the funds.

Also, this example would allow anyone to mint as long as they have sent any value, but you would probably want to change it to require a certain amount.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.