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

feat: use latest upgraded interface #26

Merged
merged 3 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion apps/contracts/contracts/interfaces/IX2EarnRewardsPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,59 @@ interface IX2EarnRewardsPool {
* @param appId the app id that is emitting the reward
* @param amount the amount of B3TR token the user is rewarded with
* @param receiver the address of the user that performed the sustainable action and is rewarded
* @param proof a JSON file uploaded on IPFS by the app that adds information on the type of action that was performed
* @param proof deprecated argument, pass an empty string instead
*/
function distributeReward(bytes32 appId, uint256 amount, address receiver, string memory proof) external;

/**
* @dev Function used by x2earn apps to reward users that performed sustainable actions.
* @notice This function is depracted in favor of distributeRewardWithProof.
*
* @param appId the app id that is emitting the reward
* @param amount the amount of B3TR token the user is rewarded with
* @param receiver the address of the user that performed the sustainable action and is rewarded
* @param proof the JSON string that contains the proof and impact of the sustainable action
*/
function distributeRewardDeprecated(bytes32 appId, uint256 amount, address receiver, string memory proof) external;

/**
* @dev Function used by x2earn apps to reward users that performed sustainable actions.
*
* @param appId the app id that is emitting the reward
* @param amount the amount of B3TR token the user is rewarded with
* @param receiver the address of the user that performed the sustainable action and is rewarded
* @param proofTypes the types of the proof of the sustainable action
* @param proofValues the values of the proof of the sustainable action
* @param impactCodes the codes of the impacts of the sustainable action
* @param impactValues the values of the impacts of the sustainable action
* @param description the description of the sustainable action
*/
function distributeRewardWithProof(
bytes32 appId,
uint256 amount,
address receiver,
string[] memory proofTypes, // link, image, video, text, etc.
string[] memory proofValues, // "https://...", "Qm...", etc.,
string[] memory impactCodes, // carbon, water, etc.
uint256[] memory impactValues, // 100, 200, etc.,
string memory description
) external;

/**
* @dev Builds the JSON proof string that will be stored
* on chain regarding the proofs, impacts and description of the sustainable action.
*
* @param proofTypes the types of the proof of the sustainable action
* @param proofValues the values of the proof of the sustainable action
* @param impactCodes the codes of the impacts of the sustainable action
* @param impactValues the values of the impacts of the sustainable action
* @param description the description of the sustainable action
*/
function buildProof(
string[] memory proofTypes, // link, photo, video, text, etc.
string[] memory proofValues, // "https://...", "Qm...", etc.,
string[] memory impactCodes, // carbon, water, etc.
uint256[] memory impactValues, // 100, 200, etc.,
string memory description
) external returns (string memory);
}
148 changes: 145 additions & 3 deletions apps/contracts/contracts/mock/X2EarnRewardsPoolMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {IX2EarnAppsMock} from './interfaces/IX2EarnAppsMock.sol';
import {IX2EarnRewardsPool} from '../interfaces/IX2EarnRewardsPool.sol';
import {IERC1155Receiver} from '@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol';
import {IERC721Receiver} from '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol';
import '@openzeppelin/contracts/utils/Strings.sol';

/**
* Mock contract forked from vebetterdao-contracts.
Expand Down Expand Up @@ -77,7 +78,7 @@ contract X2EarnRewardsPoolMock is IX2EarnRewardsPool, AccessControl, ReentrancyG
/**
* @dev See {IX2EarnRewardsPool-withdraw}
*/
function withdraw(uint256 amount, bytes32 appId, string memory reason) external nonReentrant {
function withdraw(uint256 amount, bytes32 appId, string memory reason) external {
X2EarnRewardsPoolStorage storage $ = _getX2EarnRewardsPoolStorage();

require($.x2EarnApps.appExists(appId), 'X2EarnRewardsPool: app does not exist');
Expand All @@ -103,10 +104,42 @@ contract X2EarnRewardsPoolMock is IX2EarnRewardsPool, AccessControl, ReentrancyG
emit TeamWithdrawal(amount, appId, teamWalletAddress, msg.sender, reason);
}

/**
* @dev See {IX2EarnRewardsPool-distributeRewardDeprecated}
*/
function distributeRewardDeprecated(bytes32 appId, uint256 amount, address receiver, string memory) external {
_distributeReward(appId, amount, receiver);

// emit event with empty proof
emit RewardDistributed(amount, appId, receiver, '', msg.sender);
}

/**
* @dev See {IX2EarnRewardsPool-distributeReward}
*/
function distributeReward(bytes32 appId, uint256 amount, address receiver, string memory proof) external nonReentrant {
function distributeReward(bytes32 appId, uint256 amount, address receiver, string memory) external {
_distributeReward(appId, amount, receiver);
_emitProof(appId, amount, receiver, new string[](0), new string[](0), new string[](0), new uint256[](0), '');
}

/**
* @dev See {IX2EarnRewardsPool-distributeRewardWithProof}
*/
function distributeRewardWithProof(
bytes32 appId,
uint256 amount,
address receiver,
string[] memory proofTypes, // link, photo, video, text, etc.
string[] memory proofValues, // "https://...", "Qm...", etc.,
string[] memory impactCodes, // carbon, water, etc.
uint256[] memory impactValues, // 100, 200, etc.,
string memory description
) public {
_distributeReward(appId, amount, receiver);
_emitProof(appId, amount, receiver, proofTypes, proofValues, impactCodes, impactValues, description);
}

function _distributeReward(bytes32 appId, uint256 amount, address receiver) internal nonReentrant {
X2EarnRewardsPoolStorage storage $ = _getX2EarnRewardsPoolStorage();

require($.x2EarnApps.appExists(appId), 'X2EarnRewardsPool: app does not exist');
Expand All @@ -122,9 +155,118 @@ contract X2EarnRewardsPoolMock is IX2EarnRewardsPool, AccessControl, ReentrancyG
// transfer the rewards to the receiver
$.availableFunds[appId] -= amount;
require($.b3tr.transfer(receiver, amount), 'X2EarnRewardsPool: Allocation transfer to app failed');
}

/**
* @dev Emits the RewardDistributed event with the provided proofs and impacts.
*/
function _emitProof(
bytes32 appId,
uint256 amount,
address receiver,
string[] memory proofTypes,
string[] memory proofValues,
string[] memory impactCodes,
uint256[] memory impactValues,
string memory description
) internal {
// Build the JSON proof string from the proof and impact data
string memory jsonProof = buildProof(proofTypes, proofValues, impactCodes, impactValues, description);

// emit event
emit RewardDistributed(amount, appId, receiver, proof, msg.sender);
emit RewardDistributed(amount, appId, receiver, jsonProof, msg.sender);
}

/**
* @dev see {IX2EarnRewardsPool-buildProof}
*/
function buildProof(
string[] memory proofTypes,
string[] memory proofValues,
string[] memory impactCodes,
uint256[] memory impactValues,
string memory description
) public view virtual returns (string memory) {
bool hasProof = proofTypes.length > 0 && proofValues.length > 0;
bool hasImpact = impactCodes.length > 0 && impactValues.length > 0;
bool hasDescription = bytes(description).length > 0;

// If neither proof nor impact is provided, return an empty string
if (!hasProof && !hasImpact) {
return '';
}

// Initialize an empty JSON bytes array with version
bytes memory json = abi.encodePacked('{"version": 2');

// Add description if available
if (hasDescription) {
json = abi.encodePacked(json, ',"description": "', description, '"');
}

// Add proof if available
if (hasProof) {
bytes memory jsonProof = _buildProofJson(proofTypes, proofValues);

json = abi.encodePacked(json, ',"proof": ', jsonProof);
}

// Add impact if available
if (hasImpact) {
bytes memory jsonImpact = _buildImpactJson(impactCodes, impactValues);

json = abi.encodePacked(json, ',"impact": ', jsonImpact);
}

// Close the JSON object
json = abi.encodePacked(json, '}');

return string(json);
}

/**
* @dev Builds the proof JSON string from the proof data.
* @param proofTypes the proof types
* @param proofValues the proof values
*/
function _buildProofJson(string[] memory proofTypes, string[] memory proofValues) internal pure returns (bytes memory) {
require(proofTypes.length == proofValues.length, 'X2EarnRewardsPool: Mismatched input lengths for Proof');

bytes memory json = abi.encodePacked('{');

for (uint256 i; i < proofTypes.length; i++) {
json = abi.encodePacked(json, '"', proofTypes[i], '":', '"', proofValues[i], '"');
if (i < proofTypes.length - 1) {
json = abi.encodePacked(json, ',');
}
}

json = abi.encodePacked(json, '}');

return json;
}

/**
* @dev Builds the impact JSON string from the impact data.
*
* @param impactCodes the impact codes
* @param impactValues the impact values
*/
function _buildImpactJson(string[] memory impactCodes, uint256[] memory impactValues) internal pure returns (bytes memory) {
require(impactCodes.length == impactValues.length, 'X2EarnRewardsPool: Mismatched input lengths for Impact');

bytes memory json = abi.encodePacked('{');

for (uint256 i; i < impactValues.length; i++) {
json = abi.encodePacked(json, '"', impactCodes[i], '":', Strings.toString(impactValues[i]));
if (i < impactValues.length - 1) {
json = abi.encodePacked(json, ',');
}
}

json = abi.encodePacked(json, '}');

return json;
}

/**
Expand Down
Loading
Loading