# Smart Contract Examples

**Sample Token-Gated Mint w/ Delegate**

Here the constant `ORIGINAL_CONTRACT` would be the one with the original tokens whose holders are being allowlisted. The constant`DELEGATE_REGISTRY` address would be `0x00000000000000447e69651d841bD8D104Bed493`.

```solidity
/** 
 * @notice For example, bored ape holders minting their mutant apes
 * @param originalTokenIds The ids of tokens being used to mint something new
 */
function tokengatedMint(uint256[] calldata originalTokenIds) external {
    for (uint256 i = 0; i < originalTokenIds.length; ++i) {
        uint256 tokenId = originalTokenIds[i];
        address tokenOwner = ORIGINAL_CONTRACT.ownerOf(tokenId);
        // Mint if tokenOwner is msg.sender or tokenOwner delegated to msg.sender
        if (msg.sender == tokenOwner ||
            IDelegateRegistry(DELEGATE_REGISTRY).checkDelegateForERC721(
                msg.sender,
                tokenOwner,
                address(ORIGINAL_CONTRACT),
                tokenId,
                ""
            )
        ) {
            // Can mint to either the vaulted wallet or msg.sender, project's choice
            // Can also use an `address recipient` function parameter for flexibility
            _mint(tokenOwner, tokenId);
        }
    }
}
```

**Sample Merkle Tree Claim w/ Delegate**

This is based off what [Nakamigos CLOAKS](https://etherscan.io/token/0x0c56f29b8d90eea71d57cadeb3216b4ef7494abc#code) used, where if users held a Nakamigo they were eligible for a free mint of a cloak. To save gas they used a merkle tree claim, this is compatible with Delegate.

```solidity
    /**
     * @notice Claim tokens from your allowlist quota
     * @param tokenOwner If using delegate.xyz, the address that features in the
     *  allowlist. Set this to 0x000..000 if not using delegation
     * @param numberOfTokens The number of tokens to claim
     * @param tokenQuota The total quota of tokens for the claiming address
     * @param proof The merkle proof for this claimer
     */
    function mintAllowList(
        address tokenOwner,
        uint256 numberOfTokens,
        uint256 tokenQuota,
        bytes32[] calldata proof
    ) external payable {
        // Set address of the wallet that appears on the allowlist
        address claimer = msg.sender;
        
        // --- DELEGATE INTEGRATION HERE ---

        // Check for delegation
        if (tokenOwner != address(0) && tokenOwner != msg.sender) {
            if (IDelegateRegistry(_DELEGATE_REGISTRY).checkDelegateForAll(msg.sender, tokenOwner, "")) {
                claimer = vault;
            }
        }
        
        // --- END DELEGATE INTEGRATION ---

        // Check if the claimer has tokens remaining in their quota
        if (getAllowListMinted(claimer) + numberOfTokens > tokenQuota) {
            revert ExceedsAllowListQuota();
        }

        // Check if the claimer is on the allow list
        if (!onAllowList(claimer, tokenQuota, 69000000000000000000, proof)) {
            revert NotOnAllowList();
        }

        if (msg.value != numberOfTokens * pricePerToken) {
            revert WrongETHValueSent();
        }
        
        // Claim tokens
        _setAllowListMinted(claimer, numberOfTokens);
        _safeMint(msg.sender, numberOfTokens, "");
    }
```

## General Principles

Whether you're building a mint or claim function, solidity additions to your contract are an important part of securing who is and isn't allowed to mint on behalf of a wallet.

Typically, a mint or claim function looks like this:

```solidity
function claim() public returns (uint256 tokenId) {
  // 1. Check if `msg.sender` is allowed to claim
  // Maybe using merkle tree, etc
  
  // 2. Check if `msg.sender` has already claimed
  
  // 3. Your claim code below using `msg.sender`
  _claim(msg.sender)
}
```

To integrate delegate.cash into your solidity contract, we will add a small code block to the above step. We will also pass an optional `_vault` address into the claim function.

<pre class="language-solidity" data-line-numbers><code class="lang-solidity">address constant public <a data-footnote-ref href="#user-content-fn-1">NFT_CONTRACT</a> = 0x0000000000000000000000000000000000000001;


function claim(address <a data-footnote-ref href="#user-content-fn-2">_</a>cold) public returns (uint256 tokenId) {
  address requester = msg.sender;
  
  // Check if msg.sender is a permitted delegate of the cold storage address
  // If so, then we'll move ahead and mint on behalf of the cold wallet
  // Rather than msg.sender
  if (_vault != address(0)) { 
    bool isDelegateValid = REGISTRY.checkDelegateForContract(msg.sender, _cold, NFT_CONTRACT, "");
    require(isDelegateValid, "delegation does not exist");
    requester = _cold;
  }
  
  // 1. Check if `requester` is allowed to claim
  // Maybe using merkle tree, etc
  
  // 2. Check if `requester` has already claimed
  
  // 3. Your claim code below using `requester`
  _claim(`requester`)
}
</code></pre>

Let's break down what we added.

#### (line 1) Passing an optional `_cold` address variable into the contraction.

When delegating, a <mark style="color:orange;">**hot wallet**</mark> (`msg.sender`) is the one making the request on behalf of a <mark style="color:blue;">**cold wallet**</mark> (`_cold`). When there is a `_cold` variable passed through the contract function, we know the <mark style="color:orange;">**hot wallet**</mark> is minting on someone else's behalf.

#### (line 2) Using a new `requester` variable

In a typical mint contract, `msg.sender` is used throughout the contract as the user who holds the NFT and processes the transaction. Now, since `msg.sender` may be minting on behalf of someone else, we use `requester` to know if that is the case or not. `requester` will either be `msg.sender` or the <mark style="color:blue;">**cold wallet**</mark>.

#### (line 4-8) Checking the DelegateRegistry for the valid pairings

If the transaction includes a <mark style="color:blue;">**cold wallet**</mark>, this line of code will make sure that there is a vault<>delegate pairing with the cold and hot wallet; which is the act of someone going to delegate.cash and delegating their hot wallet with their cold wallet.

[^1]: The NFT Contract of the project

[^2]: This is typically the cold wallet that holds the NFT that `msg.sender` is delegating on behalf of.
