• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ArtBlocks / artblocks-contracts / 89610423-faa7-4c2d-bf5c-40e8c7a7aa6d

03 Sep 2025 05:53PM UTC coverage: 84.926% (-0.3%) from 85.199%
89610423-faa7-4c2d-bf5c-40e8c7a7aa6d

push

circleci

web-flow
Merge pull request #1871 from ArtBlocks/ryley/pro-2136-hook-for-manuel-residency

Augmentation Hook for Block Height and Project Owned Tokens

2042 of 2690 branches covered (75.91%)

Branch coverage included in aggregate %.

0 of 16 new or added lines in 1 file covered. (0.0%)

3575 of 3924 relevant lines covered (91.11%)

340.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/packages/contracts/contracts/web3call/augment-hooks/InjectBlockHeightAndNumOwnedProjectTokens.sol
1
// SPDX-License-Identifier: LGPL-3.0-only
2
// Created By: Art Blocks Inc.
3

4
pragma solidity ^0.8.0;
5

6
import {AbstractPMPAugmentHook} from "./AbstractPMPAugmentHook.sol";
7

8
import {IWeb3Call} from "../../interfaces/v0.8.x/IWeb3Call.sol";
9
import {IERC721} from "@openzeppelin-5.0/contracts/interfaces/IERC721.sol";
10
import {Strings} from "@openzeppelin-5.0/contracts/utils/Strings.sol";
11

12
import {ABHelpers} from "../../libs/v0.8.x/ABHelpers.sol";
13

14
/**
15
 * @title InjectBlockHeightAndNumOwnedProjectTokens
16
 * @author Art Blocks Inc.
17
 * @notice This hook injects the current block height into a token's PMPs.
18
 * Also injects the quantity of token's owner's owned tokens from a
19
 * reference Art Blocks project.
20
 */
21
contract InjectBlockHeightAndNumOwnedProjectTokens is AbstractPMPAugmentHook {
22
    using Strings for uint256;
23

24
    /// @notice The address of the reference contract.
25
    address public immutable referenceContract;
26
    /// @notice The projectId of the reference project.
27
    uint256 public immutable referenceProjectId;
28
    /// @notice The number of project tokens.
29
    uint256 public immutable numReferenceTokens;
30

31
    event ReferenceContractSet(address referenceContract);
32
    event ReferenceProjectIdSet(uint256 referenceProjectId);
33
    event NumReferenceTokensSet(uint256 numReferenceTokens);
34

35
    /**
36
     * @notice Populates the referenceContract and referenceProjectId immutable variables.
37
     * @param referenceContract_ The address of the project contract.
38
     * @param referenceProjectId_ The projectId of the project.
39
     * @param numReferenceTokens_ The number of project tokens.
40
     */
41
    constructor(
42
        address referenceContract_,
43
        uint256 referenceProjectId_,
44
        uint256 numReferenceTokens_
45
    ) {
46
        // @dev keep iteration gas cost manageable by limiting numReferenceTokens
NEW
47
        require(
×
48
            numReferenceTokens_ <= 1000,
49
            "numReferenceTokens must be less than or equal to 1000"
50
        );
51
        // assign immutable variables
52
        referenceContract = referenceContract_;
53
        referenceProjectId = referenceProjectId_;
54
        numReferenceTokens = numReferenceTokens_;
55

56
        // emit events
NEW
57
        emit ReferenceContractSet(referenceContract_);
×
NEW
58
        emit ReferenceProjectIdSet(referenceProjectId_);
×
NEW
59
        emit NumReferenceTokensSet(numReferenceTokens_);
×
60
    }
61

62
    /**
63
     * @notice Augment the token parameters for a given token.
64
     * Appends the block height into a tokens PMPs.
65
     * Also injects the quantity of token's owner's owned reference tokens.
66
     * @dev This hook is called when a token's PMPs are read.
67
     * @dev This must return all desired tokenParams, not just additional data.
68
     * @param tokenParams The token parameters for the queried token.
69
     * @return augmentedTokenParams The augmented token parameters.
70
     */
71
    function onTokenPMPReadAugmentation(
72
        address coreContract,
73
        uint256 tokenId,
74
        IWeb3Call.TokenParam[] calldata tokenParams
75
    )
76
        external
77
        view
78
        override
79
        returns (IWeb3Call.TokenParam[] memory augmentedTokenParams)
80
    {
81
        // create a new tokenParam array with two extra elements
NEW
82
        uint256 originalLength = tokenParams.length;
×
NEW
83
        uint256 newLength = originalLength + 2;
×
84
        augmentedTokenParams = new IWeb3Call.TokenParam[](newLength);
85

86
        // copy the original tokenParams into the new array
NEW
87
        for (uint256 i = 0; i < originalLength; i++) {
×
88
            augmentedTokenParams[i] = tokenParams[i];
89
        }
90

91
        // get + inject the block height and owned reference tokens into the new array
NEW
92
        uint256 currentBlock = block.number;
×
93
        augmentedTokenParams[originalLength] = IWeb3Call.TokenParam({
94
            key: "BlockNumber",
95
            value: currentBlock.toString()
96
        });
97

98
        // get + inject the owned reference tokens into the new array
NEW
99
        address tokenOwner = IERC721(coreContract).ownerOf(tokenId);
×
NEW
100
        uint256 ownedReferenceTokens = _getNumberOwnedReferenceTokens(
×
101
            tokenOwner
102
        );
103
        augmentedTokenParams[originalLength + 1] = IWeb3Call.TokenParam({
104
            key: "NumOwnedReferenceTokens",
105
            value: ownedReferenceTokens.toString()
106
        });
107

108
        // return the augmented tokenParams
NEW
109
        return augmentedTokenParams;
×
110
    }
111

112
    /**
113
     * @notice Gets the number of owned reference tokens for a given token.
114
     * @param tokenOwner The owner of the token.
115
     * @return The number of owned reference tokens.
116
     */
117
    function _getNumberOwnedReferenceTokens(
118
        address tokenOwner
119
    ) internal view returns (uint256) {
NEW
120
        uint256 ownedReferenceTokens = 0;
×
121

122
        // iterate over the number of reference tokens
123
        // @dev acknowledge iteration gas cost in view function - see constructor for limit of numReferenceTokens
NEW
124
        for (uint256 i = 0; i < numReferenceTokens; i++) {
×
125
            // get the reference token id
NEW
126
            uint256 referenceTokenId = ABHelpers
×
127
                .tokenIdFromProjectIdAndTokenNumber({
128
                    projectId: referenceProjectId,
129
                    tokenNumber: i
130
                });
131

NEW
132
            if (
×
133
                IERC721(referenceContract).ownerOf(referenceTokenId) ==
134
                tokenOwner
135
            ) {
136
                ownedReferenceTokens++;
137
            }
138
        }
NEW
139
        return ownedReferenceTokens;
×
140
    }
141
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc