Skip to content

Commit

Permalink
make quest creation backwards compat
Browse files Browse the repository at this point in the history
  • Loading branch information
waynehoover committed Dec 15, 2023
1 parent 8afdd98 commit fc765a3
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 106 deletions.
251 changes: 166 additions & 85 deletions contracts/QuestFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
/// @param questId_ The id of the quest
/// @param actionType_ The action type for the quest
/// @return address the quest contract address
function create1155QuestAndQueue(
function createERC1155Quest(
address rewardTokenAddress_,
uint256 endTime_,
uint256 startTime_,
Expand All @@ -160,52 +160,52 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
string memory actionType_,
string memory questName_
) external payable nonReentrant returns (address) {
Quest storage currentQuest = quests[questId_];

if (msg.value < totalQuestNFTFee(totalParticipants_)) revert MsgValueLessThanQuestNFTFee();
if (currentQuest.questAddress != address(0)) revert QuestIdUsed();

address payable newQuest =
payable(erc1155QuestAddress.cloneDeterministic(keccak256(abi.encodePacked(msg.sender, block.chainid, block.timestamp))));
currentQuest.questAddress = address(newQuest);
currentQuest.totalParticipants = totalParticipants_;
currentQuest.questAddress.safeTransferETH(msg.value);
currentQuest.questType = "erc1155";
currentQuest.questCreator = msg.sender;
currentQuest.actionType = actionType_;
currentQuest.questName = questName_;
IQuest1155Ownable questContract = IQuest1155Ownable(newQuest);

questContract.initialize(
rewardTokenAddress_,
endTime_,
startTime_,
totalParticipants_,
tokenId_,
protocolFeeRecipient,
questId_
return createERC1155QuestInternal(
ERC1155QuestData(
rewardTokenAddress_,
endTime_,
startTime_,
totalParticipants_,
tokenId_,
questId_,
actionType_,
questName_
)
);
}

IERC1155(rewardTokenAddress_).safeTransferFrom(msg.sender, newQuest, tokenId_, totalParticipants_, "0x00");
questContract.queue();
questContract.transferOwnership(msg.sender);

emit QuestCreated(
msg.sender,
address(newQuest),
questId_,
"erc1155",
rewardTokenAddress_,
endTime_,
startTime_,
totalParticipants_,
tokenId_
/// @notice Depricated
/// @dev Create an erc1155 quest and start it at the same time. The function will transfer the reward amount to the quest contract
/// @param rewardTokenAddress_ The contract address of the reward token
/// @param endTime_ The end time of the quest
/// @param startTime_ The start time of the quest
/// @param totalParticipants_ The total amount of participants (accounts) the quest will have
/// @param tokenId_ The reward token id of the erc1155 at rewardTokenAddress_
/// @param questId_ The id of the quest
/// @return address the quest contract address
function create1155QuestAndQueue(
address rewardTokenAddress_,
uint256 endTime_,
uint256 startTime_,
uint256 totalParticipants_,
uint256 tokenId_,
string memory questId_,
string memory
) external payable nonReentrant returns (address) {
return createERC1155QuestInternal(
ERC1155QuestData(
rewardTokenAddress_,
endTime_,
startTime_,
totalParticipants_,
tokenId_,
questId_,
"",
""
)
);

return newQuest;
}

// Note: Should probably be called `createQuest()`
/// @dev Create an erc20 quest and start it at the same time. The function will transfer the reward amount to the quest contract
/// @param rewardTokenAddress_ The contract address of the reward token
/// @param endTime_ The end time of the quest
Expand All @@ -216,7 +216,7 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
/// @param actionType_ The action type for the quest
/// @param questName_ The name of the quest
/// @return address the quest contract address
function createQuestAndQueue(
function createERC20Quest(
address rewardTokenAddress_,
uint256 endTime_,
uint256 startTime_,
Expand All @@ -226,7 +226,7 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
string memory actionType_,
string memory questName_
) external checkQuest(questId_, rewardTokenAddress_) returns (address) {
address newQuest = createERC20QuestInternal(
return createERC20QuestInternal(
ERC20QuestData(
rewardTokenAddress_,
endTime_,
Expand All @@ -240,8 +240,41 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
"erc20"
)
);
transferTokensAndOwnership(newQuest, rewardTokenAddress_);
return newQuest;
}

/// @notice Depricated
/// @dev Create an erc20 quest and start it at the same time. The function will transfer the reward amount to the quest contract
/// @param rewardTokenAddress_ The contract address of the reward token
/// @param endTime_ The end time of the quest
/// @param startTime_ The start time of the quest
/// @param totalParticipants_ The total amount of participants (accounts) the quest will have
/// @param rewardAmount_ The reward amount for an erc20 quest
/// @param questId_ The id of the quest
/// @return address the quest contract address
function createQuestAndQueue(
address rewardTokenAddress_,
uint256 endTime_,
uint256 startTime_,
uint256 totalParticipants_,
uint256 rewardAmount_,
string memory questId_,
string memory,
uint256
) external checkQuest(questId_, rewardTokenAddress_) returns (address) {
return createERC20QuestInternal(
ERC20QuestData(
rewardTokenAddress_,
endTime_,
startTime_,
totalParticipants_,
rewardAmount_,
questId_,
"",
"",
0,
"erc20"
)
);
}

/*//////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -270,45 +303,6 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
this.claimOptimized{value: msg.value}(abi.encodePacked(r,vs), claimData);
}

function buildJsonString(
string memory txHash,
string memory txHashChainId,
string memory actionType,
string memory questName
) public pure returns (string memory) {
// {
// actionTxHashes: ["actionTxHash1"],
// actionNetworkChainIds: ["chainId1"],
// questName: "quest name",
// actionType: "mint"
// }
return string(abi.encodePacked(
'{"actionTxHashes":["', txHash,
'"],"actionNetworkChainIds":[', txHashChainId,
'],"questName":"', questName,
'","actionType":"', actionType, '"}'
));
}

function bytes16ToUUID(bytes16 data) public pure returns (string memory) {
bytes memory hexChars = "0123456789abcdef";
bytes memory uuid = new bytes(36); // UUID length with hyphens

uint256 j = 0; // Position in uuid
for (uint256 i = 0; i < 16; i++) {
// Insert hyphens at the appropriate positions (after 4, 6, 8, 10 bytes)
if (i == 4 || i == 6 || i == 8 || i == 10) {
uuid[j++] = '-';
}

uuid[j++] = hexChars[uint8(data[i] >> 4)];
uuid[j++] = hexChars[uint8(data[i] & 0x0F)];
}

return string(uuid);
}


function claimOptimized(bytes calldata signature_, bytes calldata data_) external payable {
(
address claimer_,
Expand Down Expand Up @@ -645,6 +639,54 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
}
}

/// @dev Internal function to create an erc1155 quest
/// @param data_ The erc20 quest data struct
function createERC1155QuestInternal(ERC1155QuestData memory data_) internal returns (address) {
Quest storage currentQuest = quests[data_.questId];

if (msg.value < totalQuestNFTFee(data_.totalParticipants)) revert MsgValueLessThanQuestNFTFee();
if (currentQuest.questAddress != address(0)) revert QuestIdUsed();

address payable newQuest =
payable(erc1155QuestAddress.cloneDeterministic(keccak256(abi.encodePacked(msg.sender, block.chainid, block.timestamp))));
currentQuest.questAddress = address(newQuest);
currentQuest.totalParticipants = data_.totalParticipants;
currentQuest.questAddress.safeTransferETH(msg.value);
currentQuest.questType = "erc1155";
currentQuest.questCreator = msg.sender;
currentQuest.actionType = data_.actionType;
currentQuest.questName = data_.questName;
IQuest1155Ownable questContract = IQuest1155Ownable(newQuest);

questContract.initialize(
data_.rewardTokenAddress,
data_.endTime,
data_.startTime,
data_.totalParticipants,
data_.tokenId,
protocolFeeRecipient,
data_.questId
);

IERC1155(data_.rewardTokenAddress).safeTransferFrom(msg.sender, newQuest, data_.tokenId, data_.totalParticipants, "0x00");
questContract.queue();
questContract.transferOwnership(msg.sender);

emit QuestCreated(
msg.sender,
address(newQuest),
data_.questId,
"erc1155",
data_.rewardTokenAddress,
data_.endTime,
data_.startTime,
data_.totalParticipants,
data_.tokenId
);

return newQuest;
}

/// @dev Internal function to create an erc20 quest
/// @param data_ The erc20 quest data struct
function createERC20QuestInternal(ERC20QuestData memory data_) internal returns (address) {
Expand Down Expand Up @@ -684,6 +726,7 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
sablierV2LockupLinearAddress
);

transferTokensAndOwnership(newQuest, data_.rewardTokenAddress);
return newQuest;
}

Expand Down Expand Up @@ -740,6 +783,44 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
questContract.transferOwnership(sender);
}

function buildJsonString(
string memory txHash,
string memory txHashChainId,
string memory actionType,
string memory questName
) internal pure returns (string memory) {
// {
// actionTxHashes: ["actionTxHash1"],
// actionNetworkChainIds: ["chainId1"],
// questName: "quest name",
// actionType: "mint"
// }
return string(abi.encodePacked(
'{"actionTxHashes":["', txHash,
'"],"actionNetworkChainIds":[', txHashChainId,
'],"questName":"', questName,
'","actionType":"', actionType, '"}'
));
}

function bytes16ToUUID(bytes16 data) internal pure returns (string memory) {
bytes memory hexChars = "0123456789abcdef";
bytes memory uuid = new bytes(36); // UUID length with hyphens

uint256 j = 0; // Position in uuid
for (uint256 i = 0; i < 16; i++) {
// Insert hyphens at the appropriate positions (after 4, 6, 8, 10 bytes)
if (i == 4 || i == 6 || i == 8 || i == 10) {
uuid[j++] = '-';
}

uuid[j++] = hexChars[uint8(data[i] >> 4)];
uuid[j++] = hexChars[uint8(data[i] & 0x0F)];
}

return string(uuid);
}

/*//////////////////////////////////////////////////////////////
DEFAULTS
//////////////////////////////////////////////////////////////*/
Expand Down
14 changes: 12 additions & 2 deletions contracts/interfaces/IQuestFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ interface IQuestFactory {
string questType;
}

struct ERC1155QuestData {
address rewardTokenAddress;
uint256 endTime;
uint256 startTime;
uint256 totalParticipants;
uint256 tokenId;
string questId;
string actionType;
string questName;
}

// Events
event ExtraMintFeeReturned(address indexed recipient, uint256 amount);
event MintFeeSet(uint256 mintFee);
Expand Down Expand Up @@ -160,8 +171,7 @@ interface IQuestFactory {
uint256 totalParticipants_,
uint256 tokenId_,
string memory questId_,
string memory actionType_,
string memory questName_
string memory
) external payable returns (address);

// Set
Expand Down
Loading

0 comments on commit fc765a3

Please sign in to comment.