# 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.delegate.xyz/integrate-in-your-project/smart-contract-examples.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
