Skip to content

Commit

Permalink
Feat: Splitting Reward contract for only native rewards
Browse files Browse the repository at this point in the history
  • Loading branch information
ogarciarevett committed Oct 9, 2024
1 parent 96e153e commit 9662d53
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 156 deletions.
53 changes: 53 additions & 0 deletions contracts/libraries/LibRewards.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

// @author Summon.xyz Team - https://summon.xyz
// @contributors: [ @ogarciarevett, @vasinl124]
//....................................................................................................................................................
//....................&&&&&&..........................................................................................................................
//..................&&&&&&&&&&&.......................................................................................................................
//..............X.....&&&&&&&&&&&&....................................................................................................................
//............&&&&&&.....&&&&&&&&&&&..................................................................................................................
//............&&&&&&&&&.....&&&&&.....................................................................................................................
//............&&&&&&&&&&&&.........&.............&&&&&&&&&&&&..&&&&....&&&&.&&&&&&&&..&&&&&&&.&&&&&&&&..&&&&&&&&.&&&&&&&&&&&&.&&&&&....&&&&...........
//...............&&&&&&&&&&&&.....&&$............&&&&..........&&&&....&&&&.&&&&&&&&.&&&&&&&&..&&&&&&&&.&&&&&&&&.&&&&&&&&&&&&.&&&&&&&..&&&&...........
//............&.....&&&&&&&&&&&&..................&&&&&&&&&&&..&&&&....&&&&.&&&&..&&&&&&.&&&&..&&&&.&&&&&&..&&&&.&&&&....&&&&.&&&&.&&&&&&&&...........
//............&&.......&&&&&&&&&&&&......................&&&&..&&&&&&&&&&&&.&&&&..&&&&&..&&&&..&&&&..&&&&...&&&&.&&&&&&&&&&&&.&&&&...&&&&&&...........
//................&&&.....&&&&&&&&&&+............&&&&&&&&&&&&...&&&&&&&&&&..&&&&...&&&&..&&&&.&&&&&..&&&&...&&&&.&&&&&&&&&&&&.&&&&....&&&&&...........
//.............&&&&&&&&&.....&&&&&&&..................................................................................................................
//.............&&&&&&&&&&&&.....&&&...................................................................................................................
//.................&&&&&&&&&&&........................................................................................................................
//....................&&&&&&&.........................................................................................................................
//....................................................................................................................................................

library LibRewards {

struct RewardTokenOld {
uint256 tokenId;
string tokenUri;
uint256 rewardAmount; // depending of the erc20 token decimal
bool isEther;
}

struct Reward {
uint256 rewardAmount;
}

struct RewardToken {
uint256 tokenId;
string tokenUri;
Reward[] rewards;
uint256 maxSupply;
}
}

library TestLibItems {
enum Tier {
NONE,
COMMON,
UNCOMMON,
RARE,
LEGENDARY,
MYTHICAL
}
}
178 changes: 22 additions & 156 deletions contracts/soulbounds/RewardsNative.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;



// @author Summon.xyz Team - https://summon.xyz
// @contributors: [ @ogarciarevett, @vasinl124]
//....................................................................................................................................................
Expand All @@ -22,16 +20,8 @@ pragma solidity ^0.8.24;
//....................&&&&&&&.........................................................................................................................
//....................................................................................................................................................

import { ERC1155 } from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import { IERC1155 } from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { ERC1155Burnable } from "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol";
import { ERC1155Supply } from "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol";
import { ERC1155Holder } from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
import { ERC721Holder } from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
import { AccessControl } from "@openzeppelin/contracts/access/AccessControl.sol";
import { ERC1155Holder } from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
import { Pausable } from "@openzeppelin/contracts/utils/Pausable.sol";
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
Expand All @@ -40,7 +30,7 @@ import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable

import { AdminERC1155Soulbound } from "../soulbounds/AdminERC1155Soulbound.sol";
import { ERCWhitelistSignature } from "../ercs/ERCWhitelistSignature.sol";
import { LibItems } from "../libraries/LibItems.sol";
import { LibRewards } from "../libraries/LibRewards.sol";

error AddressIsZero();
error InvalidTokenId();
Expand All @@ -61,8 +51,7 @@ contract Rewards is
Pausable,
ReentrancyGuard,
Initializable,
ERC1155Holder,
ERC721Holder
ERC1155Holder
{
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
Expand All @@ -74,10 +63,9 @@ contract Rewards is

uint256[] public itemIds;
mapping(uint256 => bool) private tokenExists;
mapping(uint256 => LibItems.RewardToken) public tokenRewards;
mapping(uint256 => LibRewards.RewardToken) public tokenRewards;
mapping(uint256 => bool) public isTokenMintPaused; // tokenId => bool - default is false
mapping(uint256 => bool) public isClaimRewardPaused; // tokenId => bool - default is false
mapping(uint256 => mapping(uint256 => uint256)) private erc721RewardCurrentIndex; // rewardTokenId => rewardIndex => erc721RewardCurrentIndex
mapping(uint256 => uint256) public currentRewardSupply; // rewardTokenId => currentRewardSupply

event TokenAdded(uint256 indexed tokenId);
Expand All @@ -93,6 +81,7 @@ contract Rewards is

function initialize(
address _devWallet,
address _adminWallet,
address _managerWallet,
address _minterWallet,
address _rewardTokenAddress
Expand All @@ -107,7 +96,7 @@ contract Rewards is
}

rewardTokenContract = AdminERC1155Soulbound(_rewardTokenAddress);
_grantRole(DEFAULT_ADMIN_ROLE, _devWallet);
_grantRole(DEFAULT_ADMIN_ROLE, _adminWallet);
_grantRole(DEV_CONFIG_ROLE, _devWallet);
_grantRole(MANAGER_ROLE, _managerWallet);
_grantRole(MINTER_ROLE, _minterWallet);
Expand Down Expand Up @@ -151,7 +140,7 @@ contract Rewards is
_unpause();
}

function _validateTokenInputs(LibItems.RewardToken calldata _token) private view {
function _validateTokenInputs(LibRewards.RewardToken calldata _token) private view {
if (_token.maxSupply == 0) {
revert InvalidAmount();
}
Expand All @@ -163,42 +152,18 @@ contract Rewards is
if (isTokenExist(_token.tokenId)) {
revert DupTokenId();
}

for (uint256 i = 0; i < _token.rewards.length; i++) {
LibItems.Reward memory reward = _token.rewards[i];
if (reward.rewardType != LibItems.RewardType.ETHER) {
if (reward.rewardTokenAddress == address(0)) {
revert AddressIsZero();
}
}

if (reward.rewardType == LibItems.RewardType.ERC721) {
if (
reward.rewardTokenIds.length == 0 ||
reward.rewardTokenIds.length != reward.rewardAmount * _token.maxSupply
) {
revert InvalidInput();
}
}

if (reward.rewardType != LibItems.RewardType.ERC721 && reward.rewardAmount == 0) {
revert InvalidAmount();
}
}
}

function _calculateETHRequiredForToken(LibItems.RewardToken calldata _token) private pure returns (uint256) {
function _calculateETHRequiredForToken(LibRewards.RewardToken calldata _token) private pure returns (uint256) {
uint256 totalETHRequired;
for (uint256 i = 0; i < _token.rewards.length; i++) {
LibItems.Reward memory reward = _token.rewards[i];
if (reward.rewardType == LibItems.RewardType.ETHER) {
totalETHRequired += reward.rewardAmount;
}
LibRewards.Reward memory reward = _token.rewards[i];
totalETHRequired += reward.rewardAmount;
}
return totalETHRequired * _token.maxSupply;
}

function _createTokenAndDepositRewards(LibItems.RewardToken calldata _token) private {
function _createTokenAndDepositRewards(LibRewards.RewardToken calldata _token) private {
// have to approve all the assets first
// Validate token inputs
_validateTokenInputs(_token);
Expand All @@ -211,26 +176,10 @@ contract Rewards is
address _from = _msgSender();
address _to = address(this);

for (uint256 i = 0; i < _token.rewards.length; i++) {
LibItems.Reward memory reward = _token.rewards[i];
if (reward.rewardType == LibItems.RewardType.ERC20) {
IERC20 token = IERC20(reward.rewardTokenAddress);
SafeERC20.safeTransferFrom(token, _from, _to, reward.rewardAmount * _token.maxSupply);
} else if (reward.rewardType == LibItems.RewardType.ERC721) {
IERC721 token = IERC721(reward.rewardTokenAddress);
for (uint256 j = 0; j < reward.rewardTokenIds.length; j++) {
_transferERC721(token, _from, _to, reward.rewardTokenIds[j]);
}
} else if (reward.rewardType == LibItems.RewardType.ERC1155) {
IERC1155 token = IERC1155(reward.rewardTokenAddress);
_transferERC1155(token, _from, _to, reward.rewardTokenId, reward.rewardAmount * _token.maxSupply);
}
}

emit TokenAdded(_token.tokenId);
}

function createTokenAndDepositRewards(LibItems.RewardToken calldata _token) public payable onlyRole(MANAGER_ROLE) {
function createTokenAndDepositRewards(LibRewards.RewardToken calldata _token) public payable onlyRole(MANAGER_ROLE) {
uint256 _ethRequired = _calculateETHRequiredForToken(_token);

if (msg.value < _ethRequired) {
Expand All @@ -241,7 +190,7 @@ contract Rewards is
}

function createMultipleTokensAndDepositRewards(
LibItems.RewardToken[] calldata _tokens
LibRewards.RewardToken[] calldata _tokens
) external payable onlyRole(MANAGER_ROLE) {
uint256 totalETHRequired;

Expand Down Expand Up @@ -271,42 +220,18 @@ contract Rewards is

/**
* @dev Allows the contract owner to withdraw all available assets from the contract.
* @param _rewardType The type of reward to withdraw.
* @param _to The address to send the assets to.
* @param _tokenAddress The address of the token to withdraw. (required for ERC20, ERC721, and ERC1155 tokens)
* @param _tokenIds The token IDs to withdraw. (required for ERC721 and ERC1155 tokens)
* @param _amounts The amounts to withdraw. (required for ETHER, ERC20, and ERC1155 tokens)
*/
function withdrawAssets(
LibItems.RewardType _rewardType,
address _to,
address _tokenAddress, // required for ERC20, ERC721, and ERC1155
uint256[] calldata _tokenIds, // required for ERC721 and ERC1155
uint256[] calldata _amounts // required for ETHER, ERC20, and ERC1155
uint256[] calldata _amounts
) external onlyRole(MANAGER_ROLE) {
if (_to == address(0)) {
revert AddressIsZero();
}

address _from = address(this);

if (_rewardType == LibItems.RewardType.ETHER) {
_transferEther(payable(_to), _amounts[0]);
} else if (_rewardType == LibItems.RewardType.ERC20) {
_transferERC20(IERC20(_tokenAddress), _to, _amounts[0]);
} else if (_rewardType == LibItems.RewardType.ERC721) {
IERC721 token = IERC721(_tokenAddress);
for (uint256 i = 0; i < _tokenIds.length; i++) {
_transferERC721(token, _from, _to, _tokenIds[i]);
}
} else if (_rewardType == LibItems.RewardType.ERC1155) {
if (_tokenIds.length != _amounts.length) {
revert InvalidLength();
}
for (uint256 i = 0; i < _tokenIds.length; i++) {
_transferERC1155(IERC1155(_tokenAddress), _from, _to, _tokenIds[i], _amounts[i]);
}
}
_transferEther(payable(_to), _amounts[0]);
}

function _transferEther(address payable _to, uint256 _amount) private {
Expand All @@ -320,23 +245,6 @@ contract Rewards is
}
}

function _transferERC20(IERC20 _token, address _to, uint256 _amount) private {
uint256 balanceInContract = _token.balanceOf(address(this));
if (balanceInContract < _amount) {
revert InsufficientBalance();
}

SafeERC20.safeTransfer(_token, _to, _amount);
}

function _transferERC721(IERC721 _token, address _from, address _to, uint256 _tokenId) private {
_token.safeTransferFrom(_from, _to, _tokenId);
}

function _transferERC1155(IERC1155 _token, address _from, address _to, uint256 _tokenId, uint256 _amount) private {
_token.safeTransferFrom(_from, _to, _tokenId, _amount, "");
}

function claimReward(uint256 _tokenId) external nonReentrant whenNotPaused {
_claimReward(_msgSender(), _tokenId);
}
Expand All @@ -347,12 +255,6 @@ contract Rewards is
}
}

function adminClaimReward(address _to, uint256[] calldata _tokenIds) external onlyRole(MANAGER_ROLE) whenNotPaused {
for (uint256 i = 0; i < _tokenIds.length; i++) {
_claimReward(_to, _tokenIds[i]);
}
}

function _claimReward(address _to, uint256 _rewardTokenId) private {
if (isClaimRewardPaused[_rewardTokenId]) {
revert ClaimRewardPaused();
Expand All @@ -374,37 +276,13 @@ contract Rewards is
}

function _distributeReward(address _to, uint256 _rewardTokenId) private {
LibItems.RewardToken memory _rewardToken = tokenRewards[_rewardTokenId];
LibItems.Reward[] memory rewards = _rewardToken.rewards;
LibRewards.RewardToken memory _rewardToken = tokenRewards[_rewardTokenId];
LibRewards.Reward[] memory rewards = _rewardToken.rewards;

for (uint256 i = 0; i < rewards.length; i++) {
LibItems.Reward memory reward = rewards[i];
LibRewards.Reward memory reward = rewards[i];
address _from = address(this);

if (reward.rewardType == LibItems.RewardType.ETHER) {
_transferEther(payable(_to), reward.rewardAmount);
} else if (reward.rewardType == LibItems.RewardType.ERC20) {
_transferERC20(IERC20(reward.rewardTokenAddress), _to, reward.rewardAmount);
} else if (reward.rewardType == LibItems.RewardType.ERC721) {
uint256 currentIndex = erc721RewardCurrentIndex[_rewardTokenId][i];
uint256[] memory tokenIds = reward.rewardTokenIds;
for (uint256 j = 0; j < reward.rewardAmount; j++) {
if (currentIndex >= tokenIds.length) {
revert InsufficientBalance();
}
_transferERC721(IERC721(reward.rewardTokenAddress), _from, _to, tokenIds[currentIndex + j]);
}

erc721RewardCurrentIndex[_rewardTokenId][i] += reward.rewardAmount;
} else if (reward.rewardType == LibItems.RewardType.ERC1155) {
_transferERC1155(
IERC1155(reward.rewardTokenAddress),
_from,
_to,
reward.rewardTokenId,
reward.rewardAmount
);
}
_transferEther(payable(_to), reward.rewardAmount);
}

emit Claimed(_to, _rewardTokenId, 1);
Expand Down Expand Up @@ -482,29 +360,17 @@ contract Rewards is
returns (
string memory tokenUri,
uint256 maxSupply,
LibItems.RewardType[] memory rewardTypes,
uint256[] memory rewardAmounts,
address[] memory rewardTokenAddresses,
uint256[][] memory rewardTokenIds,
uint256[] memory rewardTokenId
uint256[] memory rewardAmounts
)
{
tokenUri = tokenRewards[tokenId].tokenUri;
maxSupply = tokenRewards[tokenId].maxSupply;
LibItems.Reward[] memory rewards = tokenRewards[tokenId].rewards;
LibRewards.Reward[] memory rewards = tokenRewards[tokenId].rewards;

rewardTypes = new LibItems.RewardType[](rewards.length);
rewardAmounts = new uint256[](rewards.length);
rewardTokenAddresses = new address[](rewards.length);
rewardTokenIds = new uint256[][](rewards.length);
rewardTokenId = new uint256[](rewards.length);

for (uint i = 0; i < rewards.length; i++) {
rewardTypes[i] = rewards[i].rewardType;
rewardAmounts[i] = rewards[i].rewardAmount;
rewardTokenAddresses[i] = rewards[i].rewardTokenAddress;
rewardTokenIds[i] = rewards[i].rewardTokenIds;
rewardTokenId[i] = rewards[i].rewardTokenId;
}
}

Expand Down Expand Up @@ -563,7 +429,7 @@ contract Rewards is
// Fallback function is called when msg.data is not empty
fallback() external payable {}

function adminVerifySignature(
function devVerifySignature(
address to,
uint256 nonce,
bytes calldata data,
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 9662d53

Please sign in to comment.