# S-NFT Cards Upgrade Contract

4 cards with the same level can be craft and upgrade to one card with 1 level higher. For example, 4 level-1 cards can be craft to a 2-level card. A typical level-2 card will have more HC token mining hash rate than 4 level-1 cards combined.&#x20;

<table><thead><tr><th width="200.6250323435349">Level</th><th width="199.10857142857142">HC consumption in upgrading</th><th>HC hashrate multiplier </th></tr></thead><tbody><tr><td>1</td><td>4^level=4</td><td>/</td></tr><tr><td>2</td><td>4^level=16</td><td>100%-110%</td></tr><tr><td>3</td><td>4^level=64</td><td>110%-120%</td></tr><tr><td>4</td><td>4^level=256</td><td>120%-130%</td></tr><tr><td>5</td><td>/</td><td>130%-140%</td></tr></tbody></table>

| Level | Card used in upgrading | Bitcoin Hashrate Multiplier |
| ----- | ---------------------- | --------------------------- |
| 1     | /                      | 100%-110%                   |
| 2     | 4\*level1              | 110%-120%                   |
| 3     | 4\*level2              | 120%-130%                   |
| 4     | 4\*level3              | 130%-140%                   |
| 5     | 4\*level4              | 140%-150%                   |

Note1: HC hashrate multiplier will be determined during the upgrade by how many same character cards you used to upgrade. If you use 4 same cards to upgrade, the multiplier will be at maximum.&#x20;

Note2:If the hashrate of a level-1 card is 1.2, then when you upgrade 4 level-1 cards to get a level-2 card, the level-2 card will have a hashrate of (1.2+1.2+1.2+1.2)\*Multiplier.&#x20;

```
 function upgrade(uint256[] calldata hnIds) external nonReentrant {
        require(hnIds.length > 0, "HnIds length must > 0");
        require(hnIds.length <= 100, "HnIds length must <= 100");
        require(hnIds.length % 4 == 0, "HnIds length % 4 must == 0");
        uint256 level = hn.level(hnIds[0]);
        require(level < maxLevel, "Hn level must < max Level");
    
    uint256 upgradePrice = getUpgradePrice(hnIds);
    hc.transferFrom(msg.sender, receivingAddress, upgradePrice);

    for (uint256 index = 0; index < hnIds.length; index += 4) {
        uint256 hnId = hnIds[index];
        uint256[] memory materialHnIds = new uint256[](3);
        materialHnIds[0] = hnIds[index + 1];
        materialHnIds[1] = hnIds[index + 2];
        materialHnIds[2] = hnIds[index + 3];

        require(hn.ownerOf(hnId) == msg.sender, "This Hn is not own");
        require(hn.level(hnId) == level, "Hn level mismatch");

        uint256[] memory hashrates = hn.getHashrates(hnId);
        uint256 class = hn.getRandomNumber(hnId, "class", 1, 4);
        uint256 sameClassCount;
        for (uint256 i = 0; i < materialHnIds.length; i++) {
            require(
                hn.level(materialHnIds[i]) == level,
                "Material level mismatch"
            );

            hn.safeTransferFrom(
                msg.sender,
                address(this),
                materialHnIds[i]
            );

            uint256[] memory materialHashrates = hn.getHashrates(
                materialHnIds[i]
            );
            for (uint256 j = 0; j < hashrates.length; j++) {
                hashrates[j] += materialHashrates[j];
            }

            uint256 materialClass = hn.getRandomNumber(
                materialHnIds[i],
                "class",
                1,
                4
            );
            if (class == materialClass) sameClassCount++;
        }

        hn.setLevel(hnId, level + 1);

        for (uint256 i = 0; i < hashrates.length; i++) {
            uint256 randomness = uint256(
                keccak256(
                    abi.encodePacked(
                        msg.sender,
                        block.number,
                        upgradePrice,
                        totalUpgradeCount,
                        userUpgradeCount[msg.sender],
                        hnId,
                        materialHnIds,
                        users.length(),
                        hashrates[i],
                        i
                    )
                )
            );

            if (i == 0 && hashrates[i] == 0) {
                hashrates[i] = hcBase + (randomness % hcRange);
            } else {
                hashrates[i] =
                    (hashrates[i] *
                        (hcBase +
                            ((i == 0 ? level - 1 : level) * hashratesBase) +
                            (sameClassCount * hashratesRange) +
                            (randomness % hashratesRange))) /
                    hcBase;
            }
        }
        hn.setHashrates(hnId, hashrates);

        userUpgradeCount[msg.sender]++;
        totalUpgradeCount++;
    }

    userUpgradeAmount[msg.sender] += upgradePrice;
    totalUpgradeAmount += upgradePrice;
    users.add(msg.sender);

    emit UpgradeHns(msg.sender, hnIds);
}
```

View full code at: <https://github.com/HashlandGamefi/hashland-core/blob/main/contracts/pool/HNUpgrade.sol>


---

# 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://land-hash.gitbook.io/hashland/white-paper/hashland-application/s-nft-cards-upgrade-contract.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.
