Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Staking - ERC1155 #282

Merged
merged 5 commits into from
Nov 23, 2022
Merged

Staking - ERC1155 #282

merged 5 commits into from
Nov 23, 2022

Conversation

kumaryash90
Copy link
Member

No description provided.

Comment on lines +203 to +229
function _stake(uint256 _tokenId, uint256 _amount) internal virtual {
require(_amount != 0, "Staking 0 tokens");
address _edition = edition;

if (stakers[_tokenId][msg.sender].amountStaked > 0) {
_updateUnclaimedRewardsForStaker(_tokenId, msg.sender);
} else {
stakersArray[_tokenId].push(msg.sender);
stakers[_tokenId][msg.sender].timeOfLastUpdate = block.timestamp;
}

require(
IERC1155(_edition).balanceOf(msg.sender, _tokenId) >= _amount &&
IERC1155(_edition).isApprovedForAll(msg.sender, address(this)),
"Not balance or approved"
);
IERC1155(_edition).safeTransferFrom(msg.sender, address(this), _tokenId, _amount, "");
// stakerAddress[_tokenIds[i]] = msg.sender;
stakers[_tokenId][msg.sender].amountStaked += _amount;

if (!isIndexed[_tokenId]) {
isIndexed[_tokenId] = true;
indexedTokens.push(_tokenId);
}

emit TokensStaked(msg.sender, _tokenId, _amount);
}

Check warning

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in Staking1155._stake(uint256,uint256) (contracts/extension/Staking1155.sol#203-229): External calls: - IERC1155(_edition).safeTransferFrom(msg.sender,address(this),_tokenId,_amount,) (contracts/extension/Staking1155.sol#219) State variables written after the call(s): - stakers[_tokenId][msg.sender].amountStaked += _amount (contracts/extension/Staking1155.sol#221)
Comment on lines +205 to +231
function _stake(uint256 _tokenId, uint256 _amount) internal virtual {
require(_amount != 0, "Staking 0 tokens");
address _edition = edition;

if (stakers[_tokenId][msg.sender].amountStaked > 0) {
_updateUnclaimedRewardsForStaker(_tokenId, msg.sender);
} else {
stakersArray[_tokenId].push(msg.sender);
stakers[_tokenId][msg.sender].timeOfLastUpdate = block.timestamp;
}

require(
IERC1155(_edition).balanceOf(msg.sender, _tokenId) >= _amount &&
IERC1155(_edition).isApprovedForAll(msg.sender, address(this)),
"Not balance or approved"
);
IERC1155(_edition).safeTransferFrom(msg.sender, address(this), _tokenId, _amount, "");
// stakerAddress[_tokenIds[i]] = msg.sender;
stakers[_tokenId][msg.sender].amountStaked += _amount;

if (!isIndexed[_tokenId]) {
isIndexed[_tokenId] = true;
indexedTokens.push(_tokenId);
}

emit TokensStaked(msg.sender, _tokenId, _amount);
}

Check warning

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in Staking1155Upgradeable._stake(uint256,uint256) (contracts/extension/Staking1155Upgradeable.sol#205-231): External calls: - IERC1155(_edition).safeTransferFrom(msg.sender,address(this),_tokenId,_amount,) (contracts/extension/Staking1155Upgradeable.sol#221) State variables written after the call(s): - stakers[_tokenId][msg.sender].amountStaked += _amount (contracts/extension/Staking1155Upgradeable.sol#223)
Comment on lines +203 to +229
function _stake(uint256 _tokenId, uint256 _amount) internal virtual {
require(_amount != 0, "Staking 0 tokens");
address _edition = edition;

if (stakers[_tokenId][msg.sender].amountStaked > 0) {
_updateUnclaimedRewardsForStaker(_tokenId, msg.sender);
} else {
stakersArray[_tokenId].push(msg.sender);
stakers[_tokenId][msg.sender].timeOfLastUpdate = block.timestamp;
}

require(
IERC1155(_edition).balanceOf(msg.sender, _tokenId) >= _amount &&
IERC1155(_edition).isApprovedForAll(msg.sender, address(this)),
"Not balance or approved"
);
IERC1155(_edition).safeTransferFrom(msg.sender, address(this), _tokenId, _amount, "");
// stakerAddress[_tokenIds[i]] = msg.sender;
stakers[_tokenId][msg.sender].amountStaked += _amount;

if (!isIndexed[_tokenId]) {
isIndexed[_tokenId] = true;
indexedTokens.push(_tokenId);
}

emit TokensStaked(msg.sender, _tokenId, _amount);
}

Check notice

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in Staking1155._stake(uint256,uint256) (contracts/extension/Staking1155.sol#203-229): External calls: - IERC1155(_edition).safeTransferFrom(msg.sender,address(this),_tokenId,_amount,) (contracts/extension/Staking1155.sol#219) State variables written after the call(s): - indexedTokens.push(_tokenId) (contracts/extension/Staking1155.sol#225) - isIndexed[_tokenId] = true (contracts/extension/Staking1155.sol#224)
Comment on lines +205 to +231
function _stake(uint256 _tokenId, uint256 _amount) internal virtual {
require(_amount != 0, "Staking 0 tokens");
address _edition = edition;

if (stakers[_tokenId][msg.sender].amountStaked > 0) {
_updateUnclaimedRewardsForStaker(_tokenId, msg.sender);
} else {
stakersArray[_tokenId].push(msg.sender);
stakers[_tokenId][msg.sender].timeOfLastUpdate = block.timestamp;
}

require(
IERC1155(_edition).balanceOf(msg.sender, _tokenId) >= _amount &&
IERC1155(_edition).isApprovedForAll(msg.sender, address(this)),
"Not balance or approved"
);
IERC1155(_edition).safeTransferFrom(msg.sender, address(this), _tokenId, _amount, "");
// stakerAddress[_tokenIds[i]] = msg.sender;
stakers[_tokenId][msg.sender].amountStaked += _amount;

if (!isIndexed[_tokenId]) {
isIndexed[_tokenId] = true;
indexedTokens.push(_tokenId);
}

emit TokensStaked(msg.sender, _tokenId, _amount);
}

Check notice

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in Staking1155Upgradeable._stake(uint256,uint256) (contracts/extension/Staking1155Upgradeable.sol#205-231): External calls: - IERC1155(_edition).safeTransferFrom(msg.sender,address(this),_tokenId,_amount,) (contracts/extension/Staking1155Upgradeable.sol#221) State variables written after the call(s): - indexedTokens.push(_tokenId) (contracts/extension/Staking1155Upgradeable.sol#227) - isIndexed[_tokenId] = true (contracts/extension/Staking1155Upgradeable.sol#226)
Comment on lines +234 to +256
function _withdraw(uint256 _tokenId, uint256 _amount) internal virtual {
uint256 _amountStaked = stakers[_tokenId][msg.sender].amountStaked;
require(_amount != 0, "Withdrawing 0 tokens");
require(_amountStaked >= _amount, "Withdrawing more than staked");

_updateUnclaimedRewardsForStaker(_tokenId, msg.sender);

if (_amountStaked == _amount) {
address[] memory _stakersArray = stakersArray[_tokenId];
for (uint256 i = 0; i < _stakersArray.length; ++i) {
if (_stakersArray[i] == msg.sender) {
stakersArray[_tokenId][i] = stakersArray[_tokenId][_stakersArray.length - 1];
stakersArray[_tokenId].pop();
break;
}
}
}
stakers[_tokenId][msg.sender].amountStaked -= _amount;

IERC1155(edition).safeTransferFrom(address(this), msg.sender, _tokenId, _amount, "");

emit TokensWithdrawn(msg.sender, _tokenId, _amount);
}

Check notice

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in Staking1155Upgradeable._withdraw(uint256,uint256) (contracts/extension/Staking1155Upgradeable.sol#234-256): External calls: - IERC1155(edition).safeTransferFrom(address(this),msg.sender,_tokenId,_amount,) (contracts/extension/Staking1155Upgradeable.sol#253) Event emitted after the call(s): - TokensWithdrawn(msg.sender,_tokenId,_amount) (contracts/extension/Staking1155Upgradeable.sol#255)
Comment on lines +232 to +254
function _withdraw(uint256 _tokenId, uint256 _amount) internal virtual {
uint256 _amountStaked = stakers[_tokenId][msg.sender].amountStaked;
require(_amount != 0, "Withdrawing 0 tokens");
require(_amountStaked >= _amount, "Withdrawing more than staked");

_updateUnclaimedRewardsForStaker(_tokenId, msg.sender);

if (_amountStaked == _amount) {
address[] memory _stakersArray = stakersArray[_tokenId];
for (uint256 i = 0; i < _stakersArray.length; ++i) {
if (_stakersArray[i] == msg.sender) {
stakersArray[_tokenId][i] = stakersArray[_tokenId][_stakersArray.length - 1];
stakersArray[_tokenId].pop();
break;
}
}
}
stakers[_tokenId][msg.sender].amountStaked -= _amount;

IERC1155(edition).safeTransferFrom(address(this), msg.sender, _tokenId, _amount, "");

emit TokensWithdrawn(msg.sender, _tokenId, _amount);
}

Check notice

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in Staking1155._withdraw(uint256,uint256) (contracts/extension/Staking1155.sol#232-254): External calls: - IERC1155(edition).safeTransferFrom(address(this),msg.sender,_tokenId,_amount,) (contracts/extension/Staking1155.sol#251) Event emitted after the call(s): - TokensWithdrawn(msg.sender,_tokenId,_amount) (contracts/extension/Staking1155.sol#253)
Comment on lines +203 to +229
function _stake(uint256 _tokenId, uint256 _amount) internal virtual {
require(_amount != 0, "Staking 0 tokens");
address _edition = edition;

if (stakers[_tokenId][msg.sender].amountStaked > 0) {
_updateUnclaimedRewardsForStaker(_tokenId, msg.sender);
} else {
stakersArray[_tokenId].push(msg.sender);
stakers[_tokenId][msg.sender].timeOfLastUpdate = block.timestamp;
}

require(
IERC1155(_edition).balanceOf(msg.sender, _tokenId) >= _amount &&
IERC1155(_edition).isApprovedForAll(msg.sender, address(this)),
"Not balance or approved"
);
IERC1155(_edition).safeTransferFrom(msg.sender, address(this), _tokenId, _amount, "");
// stakerAddress[_tokenIds[i]] = msg.sender;
stakers[_tokenId][msg.sender].amountStaked += _amount;

if (!isIndexed[_tokenId]) {
isIndexed[_tokenId] = true;
indexedTokens.push(_tokenId);
}

emit TokensStaked(msg.sender, _tokenId, _amount);
}

Check notice

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in Staking1155._stake(uint256,uint256) (contracts/extension/Staking1155.sol#203-229): External calls: - IERC1155(_edition).safeTransferFrom(msg.sender,address(this),_tokenId,_amount,) (contracts/extension/Staking1155.sol#219) Event emitted after the call(s): - TokensStaked(msg.sender,_tokenId,_amount) (contracts/extension/Staking1155.sol#228)
Comment on lines +205 to +231
function _stake(uint256 _tokenId, uint256 _amount) internal virtual {
require(_amount != 0, "Staking 0 tokens");
address _edition = edition;

if (stakers[_tokenId][msg.sender].amountStaked > 0) {
_updateUnclaimedRewardsForStaker(_tokenId, msg.sender);
} else {
stakersArray[_tokenId].push(msg.sender);
stakers[_tokenId][msg.sender].timeOfLastUpdate = block.timestamp;
}

require(
IERC1155(_edition).balanceOf(msg.sender, _tokenId) >= _amount &&
IERC1155(_edition).isApprovedForAll(msg.sender, address(this)),
"Not balance or approved"
);
IERC1155(_edition).safeTransferFrom(msg.sender, address(this), _tokenId, _amount, "");
// stakerAddress[_tokenIds[i]] = msg.sender;
stakers[_tokenId][msg.sender].amountStaked += _amount;

if (!isIndexed[_tokenId]) {
isIndexed[_tokenId] = true;
indexedTokens.push(_tokenId);
}

emit TokensStaked(msg.sender, _tokenId, _amount);
}

Check notice

Code scanning / Slither

Reentrancy vulnerabilities

Reentrancy in Staking1155Upgradeable._stake(uint256,uint256) (contracts/extension/Staking1155Upgradeable.sol#205-231): External calls: - IERC1155(_edition).safeTransferFrom(msg.sender,address(this),_tokenId,_amount,) (contracts/extension/Staking1155Upgradeable.sol#221) Event emitted after the call(s): - TokensStaked(msg.sender,_tokenId,_amount) (contracts/extension/Staking1155Upgradeable.sol#230)
Comment on lines 29 to 138
uint256 private constant VERSION = 1;

/// @dev ERC20 Reward Token address. See {_mintRewards} below.
address public rewardToken;

constructor() initializer {}

/// @dev Initiliazes the contract, like a constructor.
function initialize(
address _defaultAdmin,
string memory _contractURI,
address[] memory _trustedForwarders,
address _rewardToken,
address _edition,
uint256 _defaultTimeUnit,
uint256 _defaultRewardsPerUnitTime
) external initializer {
__ReentrancyGuard_init();
__ERC2771Context_init_unchained(_trustedForwarders);

rewardToken = _rewardToken;
__Staking1155_init(_edition);
_setDefaultTimeUnit(_defaultTimeUnit);
_setDefaultRewardsPerUnitTime(_defaultRewardsPerUnitTime);

_setupContractURI(_contractURI);

_setupRole(DEFAULT_ADMIN_ROLE, _defaultAdmin);
}

/// @dev Returns the module type of the contract.
function contractType() external pure virtual returns (bytes32) {
return MODULE_TYPE;
}

/// @dev Returns the version of the contract.
function contractVersion() external pure virtual returns (uint8) {
return uint8(VERSION);
}

/*///////////////////////////////////////////////////////////////
ERC 165 / 721 logic
//////////////////////////////////////////////////////////////*/

function onERC1155Received(
address,
address,
uint256,
uint256,
bytes calldata
) external returns (bytes4) {
return this.onERC1155Received.selector;
}

function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4) {}

function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC1155ReceiverUpgradeable).interfaceId;
}

/*///////////////////////////////////////////////////////////////
Transfer Staking Rewards
//////////////////////////////////////////////////////////////*/

function _mintRewards(address _staker, uint256 _rewards) internal override {
CurrencyTransferLib.transferCurrency(rewardToken, address(this), _staker, _rewards);
}

/*///////////////////////////////////////////////////////////////
Internal functions
//////////////////////////////////////////////////////////////*/

/// @dev Returns whether staking related restrictions can be set in the given execution context.
function _canSetStakeConditions() internal view override returns (bool) {
return hasRole(DEFAULT_ADMIN_ROLE, _msgSender());
}

/// @dev Checks whether contract metadata can be set in the given execution context.
function _canSetContractURI() internal view override returns (bool) {
return hasRole(DEFAULT_ADMIN_ROLE, _msgSender());
}

/*///////////////////////////////////////////////////////////////
Miscellaneous
//////////////////////////////////////////////////////////////*/

function _msgSender() internal view virtual override returns (address sender) {
return ERC2771ContextUpgradeable._msgSender();
}

function _msgData() internal view virtual override returns (bytes calldata) {
return ERC2771ContextUpgradeable._msgData();
}
}

Check warning

Code scanning / Slither

Missing inheritance

EditionStake (contracts/staking/EditionStake.sol#29-138) should inherit from IThirdwebContract (contracts/interfaces/IThirdwebContract.sol#4-19)
Comment on lines 13 to 366
emit RewardsClaimed(msg.sender, rewards);
}

/// @dev View available rewards for a user.
function _availableRewards(uint256 _tokenId, address _user) internal view virtual returns (uint256 _rewards) {
if (stakers[_tokenId][_user].amountStaked == 0) {
_rewards = stakers[_tokenId][_user].unclaimedRewards;
} else {
_rewards = stakers[_tokenId][_user].unclaimedRewards + _calculateRewards(_tokenId, _user);
}
}

/// @dev Update unclaimed rewards for all users. Called when setting timeUnit or rewardsPerUnitTime.
function _updateUnclaimedRewardsForAll(uint256 _tokenId) internal virtual {
address[] memory _stakers = stakersArray[_tokenId];
uint256 len = _stakers.length;
for (uint256 i = 0; i < len; ++i) {
address user = _stakers[i];

uint256 rewards = _calculateRewards(_tokenId, user);
stakers[_tokenId][user].unclaimedRewards += rewards;
stakers[_tokenId][user].timeOfLastUpdate = block.timestamp;
}
}

/// @dev Update unclaimed rewards for a users. Called for every state change for a user.
function _updateUnclaimedRewardsForStaker(uint256 _tokenId, address _staker) internal virtual {
uint256 rewards = _calculateRewards(_tokenId, _staker);
stakers[_tokenId][_staker].unclaimedRewards += rewards;
stakers[_tokenId][_staker].timeOfLastUpdate = block.timestamp;
}

/// @dev Set time unit in seconds.
function _setTimeUnit(uint256 _tokenId, uint256 _timeUnit) internal virtual {
timeUnit[_tokenId] = _timeUnit;
}

/// @dev Set rewards per unit time.
function _setRewardsPerUnitTime(uint256 _tokenId, uint256 _rewardsPerUnitTime) internal virtual {
rewardsPerUnitTime[_tokenId] = _rewardsPerUnitTime;
}

/// @dev Set time unit in seconds.
function _setDefaultTimeUnit(uint256 _defaultTimeUnit) internal virtual {
defaultTimeUnit = _defaultTimeUnit;
}

/// @dev Set rewards per unit time.
function _setDefaultRewardsPerUnitTime(uint256 _defaultRewardsPerUnitTime) internal virtual {
defaultRewardsPerUnitTime = _defaultRewardsPerUnitTime;
}

/// @dev Reward calculation logic. Override to implement custom logic.
function _calculateRewards(uint256 _tokenId, address _staker) internal view virtual returns (uint256 _rewards) {
Staker memory staker = stakers[_tokenId][_staker];
uint256 _timeUnit = timeUnit[_tokenId];
uint256 _rewardsPerUnitTime = rewardsPerUnitTime[_tokenId];

if (_timeUnit == 0) _timeUnit = defaultTimeUnit;
if (_rewardsPerUnitTime == 0) _rewardsPerUnitTime = defaultRewardsPerUnitTime;

_rewards = ((((block.timestamp - staker.timeOfLastUpdate) * staker.amountStaked) * _rewardsPerUnitTime) /
_timeUnit);
}

/**
* @dev Mint ERC20 rewards to the staker. Must override.
*
* @param _staker Address for which to calculated rewards.
* @param _rewards Amount of tokens to be given out as reward.
*
* For example, override as below to mint ERC20 rewards:
*
* ```
* function _mintRewards(address _staker, uint256 _rewards) internal override {
*
* IERC20(rewardTokenAddress)._mint(_staker, _rewards);
*
* }
* ```
*/
function _mintRewards(address _staker, uint256 _rewards) internal virtual;

/**
* @dev Returns whether staking restrictions can be set in given execution context.
* Must override.
*
*
* For example, override as below to restrict access to admin:
*
* ```
* function _canSetStakeConditions() internal override {
*
* return msg.sender == adminAddress;
*
* }
* ```
*/
function _canSetStakeConditions() internal view virtual returns (bool);
}

Check warning

Code scanning / Slither

Unimplemented functions

Staking1155 (contracts/extension/Staking1155.sol#13-366) does not implement functions: - Staking1155._canSetStakeConditions() (contracts/extension/Staking1155.sol#365) - Staking1155._mintRewards(address,uint256) (contracts/extension/Staking1155.sol#348)
@kumaryash90 kumaryash90 merged commit af41ffb into main Nov 23, 2022
@nkrishang nkrishang deleted the staking-1155 branch December 26, 2022 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant