@@ -12,8 +12,13 @@ abstract contract ERC5725 is IERC5725, ERC721 {
1212 using SafeERC20 for IERC20 ;
1313
1414 /// @dev mapping for claimed payouts
15- mapping (uint256 => uint256 ) /*tokenId*/ /*claimed*/
16- internal _payoutClaimed;
15+ mapping (uint256 => uint256 ) /*tokenId*/ /*claimed*/ internal _payoutClaimed;
16+
17+ /// @dev Mapping from token ID to approved tokenId operator
18+ mapping (uint256 => address ) private _tokenIdApprovals;
19+
20+ /// @dev Mapping from owner to operator approvals
21+ mapping (address => mapping (address => bool )) /* owner */ /*(operator, isApproved)*/ internal _operatorApprovals;
1722
1823 /**
1924 * @notice Checks if the tokenId exists and its valid
@@ -28,7 +33,8 @@ abstract contract ERC5725 is IERC5725, ERC721 {
2833 * @dev See {IERC5725}.
2934 */
3035 function claim (uint256 tokenId ) external override (IERC5725 ) validToken (tokenId) {
31- require (ownerOf (tokenId) == msg .sender , "Not owner of NFT " );
36+ require (isApprovedClaimOrOwner (msg .sender , tokenId), "ERC5725: not owner or operator " );
37+
3238 uint256 amountClaimed = claimablePayout (tokenId);
3339 require (amountClaimed > 0 , "ERC5725: No pending payout " );
3440
@@ -38,6 +44,26 @@ abstract contract ERC5725 is IERC5725, ERC721 {
3844 IERC20 (payoutToken (tokenId)).safeTransfer (msg .sender , amountClaimed);
3945 }
4046
47+ /**
48+ * @dev See {IERC5725}.
49+ */
50+ function setClaimApprovalForAll (address operator , bool approved ) external override (IERC5725 ) {
51+ _setClaimApprovalForAll (operator, approved);
52+ emit ClaimApprovalForAll (msg .sender , operator, approved);
53+ }
54+
55+ /**
56+ * @dev See {IERC5725}.
57+ */
58+ function setClaimApproval (
59+ address operator ,
60+ bool approved ,
61+ uint256 tokenId
62+ ) external override (IERC5725 ) validToken (tokenId) {
63+ _setClaimApproval (operator, tokenId);
64+ emit ClaimApproval (msg .sender , operator, tokenId, approved);
65+ }
66+
4167 /**
4268 * @dev See {IERC5725}.
4369 */
@@ -48,62 +74,44 @@ abstract contract ERC5725 is IERC5725, ERC721 {
4874 /**
4975 * @dev See {IERC5725}.
5076 */
51- function vestedPayoutAtTime (uint256 tokenId , uint256 timestamp )
52- public
53- view
54- virtual
55- override (IERC5725 )
56- returns (uint256 payout );
77+ function vestedPayoutAtTime (
78+ uint256 tokenId ,
79+ uint256 timestamp
80+ ) public view virtual override (IERC5725 ) returns (uint256 payout );
5781
5882 /**
5983 * @dev See {IERC5725}.
6084 */
61- function vestingPayout (uint256 tokenId )
62- public
63- view
64- override (IERC5725 )
65- validToken (tokenId)
66- returns (uint256 payout )
67- {
85+ function vestingPayout (
86+ uint256 tokenId
87+ ) public view override (IERC5725 ) validToken (tokenId) returns (uint256 payout ) {
6888 return _payout (tokenId) - vestedPayout (tokenId);
6989 }
7090
7191 /**
7292 * @dev See {IERC5725}.
7393 */
74- function claimablePayout (uint256 tokenId )
75- public
76- view
77- override (IERC5725 )
78- validToken (tokenId)
79- returns (uint256 payout )
80- {
94+ function claimablePayout (
95+ uint256 tokenId
96+ ) public view override (IERC5725 ) validToken (tokenId) returns (uint256 payout ) {
8197 return vestedPayout (tokenId) - _payoutClaimed[tokenId];
8298 }
8399
84100 /**
85101 * @dev See {IERC5725}.
86102 */
87- function claimedPayout (uint256 tokenId )
88- public
89- view
90- override (IERC5725 )
91- validToken (tokenId)
92- returns (uint256 payout )
93- {
103+ function claimedPayout (
104+ uint256 tokenId
105+ ) public view override (IERC5725 ) validToken (tokenId) returns (uint256 payout ) {
94106 return _payoutClaimed[tokenId];
95107 }
96108
97109 /**
98110 * @dev See {IERC5725}.
99111 */
100- function vestingPeriod (uint256 tokenId )
101- public
102- view
103- override (IERC5725 )
104- validToken (tokenId)
105- returns (uint256 vestingStart , uint256 vestingEnd )
106- {
112+ function vestingPeriod (
113+ uint256 tokenId
114+ ) public view override (IERC5725 ) validToken (tokenId) returns (uint256 vestingStart , uint256 vestingEnd ) {
107115 return (_startTime (tokenId), _endTime (tokenId));
108116 }
109117
@@ -116,18 +124,81 @@ abstract contract ERC5725 is IERC5725, ERC721 {
116124
117125 /**
118126 * @dev See {IERC165-supportsInterface}.
119- * IERC5725 interfaceId = 0x7c89676d
120- */
121- function supportsInterface (bytes4 interfaceId )
122- public
123- view
124- virtual
125- override (ERC721 , IERC165 )
126- returns (bool supported )
127- {
127+ * IERC5725 interfaceId = 0xbd3a202b
128+ */
129+ function supportsInterface (
130+ bytes4 interfaceId
131+ ) public view virtual override (ERC721 , IERC165 ) returns (bool supported ) {
128132 return interfaceId == type (IERC5725 ).interfaceId || super .supportsInterface (interfaceId);
129133 }
130134
135+ /**
136+ * @dev See {IERC5725}.
137+ */
138+ function getClaimApproved (uint256 tokenId ) public view returns (address operator ) {
139+ return _tokenIdApprovals[tokenId];
140+ }
141+
142+ /**
143+ * @dev Returns true if `owner` has set `operator` to manage all `tokenId`s.
144+ * @param owner The owner allowing `operator` to manage all `tokenId`s.
145+ * @param operator The address who is given permission to spend tokens on behalf of the `owner`.
146+ */
147+ function isClaimApprovedForAll (address owner , address operator ) public view returns (bool isClaimApproved ) {
148+ return _operatorApprovals[owner][operator];
149+ }
150+
151+ /**
152+ * @dev Public view which returns true if the operator has permission to claim for `tokenId`
153+ * @notice To remove permissions, set operator to zero address.
154+ *
155+ * @param operator The address that has permission for a `tokenId`.
156+ * @param tokenId The NFT `tokenId`.
157+ */
158+ function isApprovedClaimOrOwner (address operator , uint256 tokenId ) public view virtual returns (bool ) {
159+ address owner = ownerOf (tokenId);
160+ return (operator == owner || isClaimApprovedForAll (owner, operator) || getClaimApproved (tokenId) == operator);
161+ }
162+
163+ /**
164+ * @dev Internal function to set the operator status for a given owner to manage all `tokenId`s.
165+ * @notice To remove permissions, set approved to false.
166+ *
167+ * @param operator The address who is given permission to spend vested tokens.
168+ * @param approved The approved status.
169+ */
170+ function _setClaimApprovalForAll (address operator , bool approved ) internal virtual {
171+ _operatorApprovals[msg .sender ][operator] = approved;
172+ }
173+
174+ /**
175+ * @dev Internal function to set the operator status for a given tokenId.
176+ * @notice To remove permissions, set operator to zero address.
177+ *
178+ * @param operator The address who is given permission to spend vested tokens.
179+ * @param tokenId The NFT `tokenId`.
180+ */
181+ function _setClaimApproval (address operator , uint256 tokenId ) internal virtual {
182+ require (ownerOf (tokenId) == msg .sender , "ERC5725: not owner of tokenId " );
183+ _tokenIdApprovals[tokenId] = operator;
184+ }
185+
186+ /**
187+ * @dev Internal function to hook into {IERC721-_afterTokenTransfer}, when a token is being transferred.
188+ * Removes permissions to _tokenIdApprovals[tokenId] when the tokenId is transferred, burnt, but not on mint.
189+ *
190+ * @param from The address from which the tokens are being transferred.
191+ * @param to The address to which the tokens are being transferred.
192+ * @param firstTokenId The first tokenId in the batch that is being transferred.
193+ * @param batchSize The number of tokens being transferred in this batch.
194+ */
195+ function _beforeTokenTransfer (address from , address to , uint256 firstTokenId , uint256 batchSize ) internal override {
196+ super ._beforeTokenTransfer (from, to, firstTokenId, batchSize);
197+ if (from != address (0 )) {
198+ delete _tokenIdApprovals[firstTokenId];
199+ }
200+ }
201+
131202 /**
132203 * @dev Internal function to get the payout token of a given vesting NFT
133204 *
0 commit comments