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

Update QuestBudget Fee Calculation #289

Merged
merged 10 commits into from
Jul 19, 2024
97 changes: 97 additions & 0 deletions broadcast/Quest.s.sol/11155111/run-1720556566.json

Large diffs are not rendered by default.

68 changes: 34 additions & 34 deletions broadcast/Quest.s.sol/11155111/run-latest.json

Large diffs are not rendered by default.

175 changes: 175 additions & 0 deletions broadcast/QuestBudget.s.sol/11155111/run-1720557285.json

Large diffs are not rendered by default.

159 changes: 78 additions & 81 deletions broadcast/QuestBudget.s.sol/11155111/run-latest.json

Large diffs are not rendered by default.

113 changes: 113 additions & 0 deletions broadcast/QuestFactory.s.sol/11155111/run-1720556469.json

Large diffs are not rendered by default.

47 changes: 47 additions & 0 deletions broadcast/QuestFactory.s.sol/11155111/run-1720556619.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"transactions": [
{
"hash": "0x03bc1337f2c1f762fc4d9baee50a9007ce1752b47a506b13126b6829c516f760",
"transactionType": "CALL",
"contractName": "TransparentUpgradeableProxy",
"contractAddress": "0x52629961f71c1c2564c5aa22372cb1b9fa9eba3e",
"function": null,
"arguments": null,
"transaction": {
"from": "0x017f8ad14a2e745ea0f756bd57cd4852400be78c",
"to": "0x52629961f71c1c2564c5aa22372cb1b9fa9eba3e",
"gas": "0x11dae",
"value": "0x0",
"input": "0x086575ae00000000000000000000000000000000000000000000000000000000000000fa",
"nonce": "0x1a0",
"chainId": "0xaa36a7"
},
"additionalContracts": [],
"isFixedGasLimit": false
}
],
"receipts": [
{
"status": "0x1",
"cumulativeGasUsed": "0x12d3ce7",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"type": "0x2",
"transactionHash": "0x03bc1337f2c1f762fc4d9baee50a9007ce1752b47a506b13126b6829c516f760",
"transactionIndex": "0x78",
"blockHash": "0x338eb0c2ac8c2eb45d7decff9ecd9ef5b338a9b233c299d2b909f7a06954ab04",
"blockNumber": "0x5fce40",
"gasUsed": "0xced4",
"effectiveGasPrice": "0x41b29c53",
"from": "0x017f8ad14a2e745ea0f756bd57cd4852400be78c",
"to": "0x52629961f71c1c2564c5aa22372cb1b9fa9eba3e",
"contractAddress": null
}
],
"libraries": [],
"pending": [],
"returns": {},
"timestamp": 1720556619,
"chain": 11155111,
"commit": "7bc400a"
}
26 changes: 13 additions & 13 deletions broadcast/QuestFactory.s.sol/11155111/run-latest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"transactions": [
{
"hash": "0x46b08ba8ceb5c8759f9b53accfee98f5201af9aa2854531e81651c60ba066883",
"hash": "0x03bc1337f2c1f762fc4d9baee50a9007ce1752b47a506b13126b6829c516f760",
"transactionType": "CALL",
"contractName": "TransparentUpgradeableProxy",
"contractAddress": "0x52629961f71c1c2564c5aa22372cb1b9fa9eba3e",
Expand All @@ -10,10 +10,10 @@
"transaction": {
"from": "0x017f8ad14a2e745ea0f756bd57cd4852400be78c",
"to": "0x52629961f71c1c2564c5aa22372cb1b9fa9eba3e",
"gas": "0xd211",
"gas": "0x11dae",
"value": "0x0",
"input": "0xe1bc3aba00000000000000000000000000000000000000000000000000000000000000fa",
"nonce": "0x197",
"input": "0x086575ae00000000000000000000000000000000000000000000000000000000000000fa",
"nonce": "0x1a0",
"chainId": "0xaa36a7"
},
"additionalContracts": [],
Expand All @@ -23,16 +23,16 @@
"receipts": [
{
"status": "0x1",
"cumulativeGasUsed": "0x78ba80",
"cumulativeGasUsed": "0x12d3ce7",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"type": "0x2",
"transactionHash": "0x46b08ba8ceb5c8759f9b53accfee98f5201af9aa2854531e81651c60ba066883",
"transactionIndex": "0x3f",
"blockHash": "0x44461736fc1e4e06bd05c0cb28510593ffc3d39f61f0a2ea3a361081a556ba30",
"blockNumber": "0x5e43f9",
"gasUsed": "0x8fa3",
"effectiveGasPrice": "0x3f25c9071",
"transactionHash": "0x03bc1337f2c1f762fc4d9baee50a9007ce1752b47a506b13126b6829c516f760",
"transactionIndex": "0x78",
"blockHash": "0x338eb0c2ac8c2eb45d7decff9ecd9ef5b338a9b233c299d2b909f7a06954ab04",
"blockNumber": "0x5fce40",
"gasUsed": "0xced4",
"effectiveGasPrice": "0x41b29c53",
"from": "0x017f8ad14a2e745ea0f756bd57cd4852400be78c",
"to": "0x52629961f71c1c2564c5aa22372cb1b9fa9eba3e",
"contractAddress": null
Expand All @@ -41,7 +41,7 @@
"libraries": [],
"pending": [],
"returns": {},
"timestamp": 1719249950,
"timestamp": 1720556619,
"chain": 11155111,
"commit": "42a9cc2"
"commit": "7bc400a"
}
5 changes: 3 additions & 2 deletions contracts/Quest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ contract Quest is ReentrancyGuardUpgradeable, PausableUpgradeable, Ownable, IQue
uint256 rewardAmountInWei_,
string memory questId_,
uint16 questFee_,
address protocolFeeRecipient_
address protocolFeeRecipient_,
uint16 referralRewardFee_
) external initializer {
// Validate inputs
if (endTime_ <= block.timestamp) revert EndTimeInPast();
Expand All @@ -84,7 +85,7 @@ contract Quest is ReentrancyGuardUpgradeable, PausableUpgradeable, Ownable, IQue
queued = true;
referralClaimTotal = 0;
totalReferralsFeesClaimed = 0;
referralRewardFee = 250; // 2.5%
referralRewardFee = referralRewardFee_;
_initializeOwner(msg.sender);
__Pausable_init();
__ReentrancyGuard_init();
Expand Down
6 changes: 4 additions & 2 deletions contracts/QuestBudget.sol
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,10 @@ contract QuestBudget is Budget, IERC1155Receiver, ReentrancyGuard {
) public virtual onlyAuthorized returns (address) {
uint256 maxTotalRewards = totalParticipants_ * rewardAmount_;
uint256 questFee = uint256(IQuestFactory(questFactory).questFee());
uint256 maxProtocolReward = (maxTotalRewards * questFee) / 10_000; // Assuming questFee is 2000
uint256 approvalAmount = maxTotalRewards + maxProtocolReward;
uint256 referralRewardFee = uint256(IQuestFactory(questFactory).referralRewardFee());
uint256 maxProtocolReward = (maxTotalRewards * questFee) / 10_000;
uint256 maxReferralReward = (maxTotalRewards * referralRewardFee) / 10_000;
uint256 approvalAmount = maxTotalRewards + maxProtocolReward + maxReferralReward;
rewardTokenAddress_.safeApprove(address(questFactory), approvalAmount);
return IQuestFactory(questFactory).createERC20Quest(
txHashChainId_,
Expand Down
30 changes: 23 additions & 7 deletions contracts/QuestFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
address private __deprecated_sablierV2LockupLinearAddress; // not used
mapping(address => address) private __deprecated_mintFeeRecipientList; // not used
uint256 public referralRewardTimestamp;
uint16 public referralRewardFee; // fee on erc20 token
// insert new vars here at the end to keep the storage layout the same

/*//////////////////////////////////////////////////////////////
Expand All @@ -76,7 +77,7 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
uint256 mintFee_
) external initializer {
_initializeOwner(ownerAddress_);
questFee = 2000; // in BIPS
questFee = 250; // in BIPS
locked = 1;
claimSignerAddress = claimSignerAddress_;
protocolFeeRecipient = protocolFeeRecipient_;
Expand All @@ -85,6 +86,7 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
referralFee = referralFee_;
mintFee = mintFee_;
referralRewardTimestamp = block.timestamp;
referralRewardFee = 250; // in BIPS
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The referralFee on line 86 refers to the referral fees on the claim fee (which is currently set to 0 ETH)

}

/*//////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -170,12 +172,13 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
actionType_,
questName_,
"erc20",
projectName_
projectName_,
referralRewardFee
)
);
}

/// @dev Create an erc20 quest and start it at the same time. The function will transfer the reward amount to the quest contract
/// @dev Create an erc20 quest and start it at the same time. The function will transfer the reward amount to the quest contract
/// @param txHashChainId_ The chain id of the chain the txHash is on
/// @param rewardTokenAddress_ The contract address of the reward token
/// @param endTime_ The end time of the quest
Expand Down Expand Up @@ -213,7 +216,8 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
actionType_,
questName_,
"erc20",
projectName_
projectName_,
referralRewardFee
)
);
}
Expand Down Expand Up @@ -334,7 +338,8 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
actionType_,
questName_,
"erc20",
""
"",
referralRewardFee
)
);
}
Expand Down Expand Up @@ -362,7 +367,8 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
"",
"",
"erc20",
""
"",
referralRewardFee
)
);
}
Expand Down Expand Up @@ -546,6 +552,14 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
questFee = questFee_;
}

/// @dev set the referral reward fee (erc20 tokens)
/// @notice the referral reward fee should be in Basis Point units
/// @param referralRewardFee_ The referral reward fee value
function setReferralRewardFee(uint16 referralRewardFee_) external onlyOwner {
if (referralRewardFee_ > 10_000) revert ReferralFeeTooHigh();
referralRewardFee = referralRewardFee_;
}

/// @dev set the referral fee
/// @param referralFee_ The value of the referralFee
function setReferralFee(uint16 referralFee_) external onlyOwner {
Expand Down Expand Up @@ -853,6 +867,7 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
currentQuest.actionType = data_.actionType;
currentQuest.questName = data_.questName;
currentQuest.txHashChainId = data_.txHashChainId;
currentQuest.referralRewardFee = data_.referralRewardFee;

emit QuestCreated(
msg.sender,
Expand All @@ -878,7 +893,8 @@ contract QuestFactory is Initializable, LegacyStorage, OwnableRoles, IQuestFacto
data_.rewardAmount,
data_.questId,
questFee,
protocolFeeRecipient
protocolFeeRecipient,
referralRewardFee
);

transferTokensAndOwnership(newQuest, data_.rewardTokenAddress);
Expand Down
3 changes: 2 additions & 1 deletion contracts/interfaces/IQuest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ interface IQuest {
uint256 rewardAmountInWei_,
string memory questId_,
uint16 questFee_,
address protocolFeeRecipient_
address protocolFeeRecipient_,
uint16 referraalRewardFee_
) external;
function getRewardAmount() external view returns (uint256);
function getRewardToken() external view returns (address);
Expand Down
3 changes: 3 additions & 0 deletions contracts/interfaces/IQuestFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ interface IQuestFactory {
string actionType;
string questName;
uint32 txHashChainId;
uint16 referralRewardFee;
}

struct QuestData {
Expand Down Expand Up @@ -89,6 +90,7 @@ interface IQuestFactory {
string questName;
string questType;
string projectName;
uint16 referralRewardFee;
}

struct ERC1155QuestData {
Expand Down Expand Up @@ -194,6 +196,7 @@ interface IQuestFactory {
string memory questName
) external pure returns (string memory);
function questFee() external view returns (uint16);
function referralRewardFee() external view returns (uint16);

// Create
function createERC20Boost(
Expand Down
6 changes: 3 additions & 3 deletions script/QuestBudget.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import {LibClone} from "solady/utils/LibClone.sol";

contract QuestBudgetDeploy is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("TEST_CLAIM_SIGNER_PRIVATE_KEY");
address operator = vm.envAddress("MAINNET_QUEST_BUDGET_OPERATOR");
address owner = vm.envAddress("MAINNET_QUEST_BUDGET_OWNER");
uint256 deployerPrivateKey = vm.envUint("QUEST_BUDGET_DEPLOYER_PRIVATE_KEY");
address operator = vm.envAddress("QUEST_BUDGET_OPERATOR");
address owner = vm.envAddress("QUEST_BUDGET_OWNER");
address[] memory authorized = new address[](1);
authorized[0] = operator; // Add more authorized addresses if needed

Expand Down
20 changes: 13 additions & 7 deletions test/Quest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ contract TestQuest is Test, TestUtils, Errors, Events {
uint256 TOTAL_PARTICIPANTS = 300;
uint256 REWARD_AMOUNT_IN_WEI = 10_000_000_000;
string QUEST_ID = "QUEST_ID";
uint16 QUEST_FEE = 2000; // 20%
uint16 QUEST_FEE = 250; // 2.5%
uint256 CLAIM_FEE = 999;
uint16 REFERRAL_REWARD_FEE = 250; // 2.5%
address protocolFeeRecipient = makeAddr("protocolFeeRecipient");
Expand Down Expand Up @@ -58,7 +58,8 @@ contract TestQuest is Test, TestUtils, Errors, Events {
REWARD_AMOUNT_IN_WEI,
QUEST_ID,
QUEST_FEE,
protocolFeeRecipient
protocolFeeRecipient,
REFERRAL_REWARD_FEE
);
// Transfer all tokens to quest
vm.prank(admin);
Expand Down Expand Up @@ -96,7 +97,8 @@ contract TestQuest is Test, TestUtils, Errors, Events {
REWARD_AMOUNT_IN_WEI,
QUEST_ID,
QUEST_FEE,
protocolFeeRecipient
protocolFeeRecipient,
REFERRAL_REWARD_FEE
);
}

Expand All @@ -113,7 +115,8 @@ contract TestQuest is Test, TestUtils, Errors, Events {
REWARD_AMOUNT_IN_WEI,
QUEST_ID,
QUEST_FEE,
protocolFeeRecipient
protocolFeeRecipient,
REFERRAL_REWARD_FEE
);
}

Expand Down Expand Up @@ -200,7 +203,8 @@ contract TestQuest is Test, TestUtils, Errors, Events {
rewardAmountInWei,
QUEST_ID,
QUEST_FEE,
protocolFeeRecipient
protocolFeeRecipient,
REFERRAL_REWARD_FEE
);
// Transfer all tokens to quest
vm.prank(admin);
Expand Down Expand Up @@ -328,7 +332,8 @@ contract TestQuest is Test, TestUtils, Errors, Events {
REWARD_AMOUNT_IN_WEI,
QUEST_ID,
QUEST_FEE,
protocolFeeRecipient
protocolFeeRecipient,
REFERRAL_REWARD_FEE
);

vm.startPrank(admin);
Expand Down Expand Up @@ -435,7 +440,8 @@ contract TestQuest is Test, TestUtils, Errors, Events {
REWARD_AMOUNT_IN_WEI,
QUEST_ID,
QUEST_FEE,
protocolFeeRecipient
protocolFeeRecipient,
REFERRAL_REWARD_FEE
);

vm.startPrank(admin);
Expand Down
16 changes: 10 additions & 6 deletions test/QuestBudget.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -383,12 +383,14 @@ contract QuestBudgetTest is Test, TestUtils, IERC1155Receiver {
string memory actionType_ = "testAction";
string memory questName_ = "Test Quest";
string memory projectName_ = "Test Project";
uint256 referralRewardFee_ = 10 ether;
uint256 referralRewardFee_ = 250;

uint256 maxTotalRewards = totalParticipants_ * rewardAmount_;
uint256 questFee = uint256(mockQuestFactory.questFee());
uint256 maxProtocolReward = (maxTotalRewards * questFee) / 10_000; // Assuming questFee is 2000
uint256 approvalAmount = maxTotalRewards + maxProtocolReward;
uint256 referralRewardFee = uint256(mockQuestFactory.referralRewardFee());
uint256 maxProtocolReward = (maxTotalRewards * questFee) / 10_000;
uint256 maxReferralReward = (maxTotalRewards * referralRewardFee) / 10_000;
uint256 approvalAmount = maxTotalRewards + maxProtocolReward + maxReferralReward;
mockERC20.mint(address(this), approvalAmount);
// Ensure the budget has enough tokens for the reward
mockERC20.approve(address(questBudget), approvalAmount);
Expand Down Expand Up @@ -434,12 +436,14 @@ contract QuestBudgetTest is Test, TestUtils, IERC1155Receiver {
string memory actionType_ = "testAction";
string memory questName_ = "Test Quest";
string memory projectName_ = "Test Project";
uint256 referralRewardFee_ = 10 ether;
uint256 referralRewardFee_ = 250;

uint256 maxTotalRewards = totalParticipants_ * rewardAmount_;
uint256 questFee = uint256(mockQuestFactory.questFee());
uint256 maxProtocolReward = (maxTotalRewards * questFee) / 10_000; // Assuming questFee is 2000
uint256 approvalAmount = maxTotalRewards + maxProtocolReward;
uint256 referralRewardFee = uint256(mockQuestFactory.referralRewardFee());
uint256 maxProtocolReward = (maxTotalRewards * questFee) / 10_000;
uint256 maxReferralReward = (maxTotalRewards * referralRewardFee) / 10_000;
uint256 approvalAmount = maxTotalRewards + maxProtocolReward + maxReferralReward;
mockERC20.mint(address(this), approvalAmount);
// Ensure the budget has enough tokens for the reward
mockERC20.approve(address(questBudget), approvalAmount);
Expand Down
Loading
Loading