-
Notifications
You must be signed in to change notification settings - Fork 527
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
Staking - ERC1155 #282
Conversation
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
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
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
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
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
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
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
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
contracts/staking/EditionStake.sol
Outdated
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
contracts/extension/Staking1155.sol
Outdated
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
No description provided.