@@ -12,19 +12,25 @@ import "./interface/IStaking.sol";
1212
1313abstract contract Staking721Upgradeable is ReentrancyGuardUpgradeable , IStaking {
1414 /*///////////////////////////////////////////////////////////////
15- State variables
15+ State variables / Mappings
1616 //////////////////////////////////////////////////////////////*/
1717
18+ ///@dev Address of ERC721 NFT contract -- staked tokens belong to this contract.
19+ address public nftCollection;
20+
1821 /// @dev Unit of time specified in number of seconds. Can be set as 1 seconds, 1 days, 1 hours, etc.
1922 uint256 public timeUnit;
2023
2124 ///@dev Rewards accumulated per unit of time.
2225 uint256 public rewardsPerUnitTime;
2326
24- ///@dev Address of ERC721 NFT contract -- staked tokens belong to this contract.
25- address public nftCollection;
27+ ///@dev List of token-ids ever staked.
28+ uint256 [] public indexedTokens;
29+
30+ ///@dev Mapping from token-id to whether it is indexed or not.
31+ mapping (uint256 => bool ) public isIndexed;
2632
27- ///@dev Mapping from staker address to Staker struct. See {struct IStaking .Staker}.
33+ ///@dev Mapping from staker address to Staker struct. See {struct IStaking721 .Staker}.
2834 mapping (address => Staker) public stakers;
2935
3036 /// @dev Mapping from staked token-id to staker address.
@@ -123,10 +129,35 @@ abstract contract Staking721Upgradeable is ReentrancyGuardUpgradeable, IStaking
123129 /**
124130 * @notice View amount staked and total rewards for a user.
125131 *
126- * @param _staker Address for which to calculated rewards.
132+ * @param _staker Address for which to calculated rewards.
133+ * @return _tokensStaked List of token-ids staked by staker.
134+ * @return _rewards Available reward amount.
127135 */
128- function getStakeInfo (address _staker ) public view virtual returns (uint256 _tokensStaked , uint256 _rewards ) {
129- _tokensStaked = stakers[_staker].amountStaked;
136+ function getStakeInfo (address _staker )
137+ public
138+ view
139+ virtual
140+ returns (uint256 [] memory _tokensStaked , uint256 _rewards )
141+ {
142+ uint256 [] memory _indexedTokens = indexedTokens;
143+ bool [] memory _isStakerToken = new bool [](_indexedTokens.length );
144+ uint256 indexedTokenCount = _indexedTokens.length ;
145+ uint256 stakerTokenCount = 0 ;
146+
147+ for (uint256 i = 0 ; i < indexedTokenCount; i++ ) {
148+ _isStakerToken[i] = stakerAddress[_indexedTokens[i]] == _staker;
149+ if (_isStakerToken[i]) stakerTokenCount += 1 ;
150+ }
151+
152+ _tokensStaked = new uint256 [](stakerTokenCount);
153+ uint256 count = 0 ;
154+ for (uint256 i = 0 ; i < indexedTokenCount; i++ ) {
155+ if (_isStakerToken[i]) {
156+ _tokensStaked[count] = _indexedTokens[i];
157+ count += 1 ;
158+ }
159+ }
160+
130161 _rewards = _availableRewards (_staker);
131162 }
132163
@@ -139,16 +170,28 @@ abstract contract Staking721Upgradeable is ReentrancyGuardUpgradeable, IStaking
139170 uint256 len = _tokenIds.length ;
140171 require (len != 0 , "Staking 0 tokens " );
141172
173+ address _nftCollection = nftCollection;
174+
142175 if (stakers[msg .sender ].amountStaked > 0 ) {
143176 _updateUnclaimedRewardsForStaker (msg .sender );
144177 } else {
145178 stakersArray.push (msg .sender );
146179 stakers[msg .sender ].timeOfLastUpdate = block .timestamp ;
147180 }
148181 for (uint256 i = 0 ; i < len; ++ i) {
149- require (IERC721 (nftCollection).ownerOf (_tokenIds[i]) == msg .sender , "Not owner " );
150- IERC721 (nftCollection).transferFrom (msg .sender , address (this ), _tokenIds[i]);
182+ require (
183+ IERC721 (_nftCollection).ownerOf (_tokenIds[i]) == msg .sender &&
184+ (IERC721 (_nftCollection).getApproved (_tokenIds[i]) == address (this ) ||
185+ IERC721 (_nftCollection).isApprovedForAll (msg .sender , address (this ))),
186+ "Not owned or approved "
187+ );
188+ IERC721 (_nftCollection).transferFrom (msg .sender , address (this ), _tokenIds[i]);
151189 stakerAddress[_tokenIds[i]] = msg .sender ;
190+
191+ if (! isIndexed[_tokenIds[i]]) {
192+ isIndexed[_tokenIds[i]] = true ;
193+ indexedTokens.push (_tokenIds[i]);
194+ }
152195 }
153196 stakers[msg .sender ].amountStaked += len;
154197
@@ -162,6 +205,8 @@ abstract contract Staking721Upgradeable is ReentrancyGuardUpgradeable, IStaking
162205 require (len != 0 , "Withdrawing 0 tokens " );
163206 require (_amountStaked >= len, "Withdrawing more than staked " );
164207
208+ address _nftCollection = nftCollection;
209+
165210 _updateUnclaimedRewardsForStaker (msg .sender );
166211
167212 if (_amountStaked == len) {
@@ -177,7 +222,7 @@ abstract contract Staking721Upgradeable is ReentrancyGuardUpgradeable, IStaking
177222 for (uint256 i = 0 ; i < len; ++ i) {
178223 require (stakerAddress[_tokenIds[i]] == msg .sender , "Not staker " );
179224 stakerAddress[_tokenIds[i]] = address (0 );
180- IERC721 (nftCollection ).transferFrom (address (this ), msg .sender , _tokenIds[i]);
225+ IERC721 (_nftCollection ).transferFrom (address (this ), msg .sender , _tokenIds[i]);
181226 }
182227
183228 emit TokensWithdrawn (msg .sender , _tokenIds);
@@ -244,7 +289,7 @@ abstract contract Staking721Upgradeable is ReentrancyGuardUpgradeable, IStaking
244289 }
245290
246291 /**
247- * @dev Mint ERC20 rewards to the staker. Must override.
292+ * @dev Mint/Transfer ERC20 rewards to the staker. Must override.
248293 *
249294 * @param _staker Address for which to calculated rewards.
250295 * @param _rewards Amount of tokens to be given out as reward.
@@ -254,7 +299,7 @@ abstract contract Staking721Upgradeable is ReentrancyGuardUpgradeable, IStaking
254299 * ```
255300 * function _mintRewards(address _staker, uint256 _rewards) internal override {
256301 *
257- * IERC20 (rewardTokenAddress)._mint (_staker, _rewards);
302+ * TokenERC20 (rewardTokenAddress).mintTo (_staker, _rewards);
258303 *
259304 * }
260305 * ```
0 commit comments