I need help with a function to reward user with erc777-token as soon as his content (Ipfs-Hash, see the program below) hit n-number of likes (lets say every 100th like), i.e., whenever the 'netLike' counter hits 100, it automatically mints one token to the respective user's address.
And because there's a dislike function as well, the user should not be rewarded the token every time the likeCounter hits 100, (for example - if a user hits 100th like for the first time, its rewarded with one erc token, and once it hits that milestone, in order to earn 2nd token, it must hit the milestone of 200 likes, and likewise every multiple of 100 can only generate one token 'one-time')
I've added nonce for this purpose, but couldn't really figure out the exact logic!! (brainfog 😊) The logic and the _mint() fn is inside the like function.
Thanks!!
Content[] public contents;
// A mapping of Content Hashes to their respective Owners
mapping(bytes32 => address) public contentHashToAuthor;
//Contains all the indices of content uploaded by the author
mapping(address => uint256[]) public authorToContentIndices;
//A mapping of contentHash to contentIndex
mapping(bytes32 => uint256) contentIndex;
//the struct that contains the content-Info
struct Content{
bytes32 hash;
string[] tags;
address author;
uint256 likes;
uint256 dislikes;
int256 netLikes;
uint256 nonce;
uint64 timeStamp;
}
function addContent(bytes32[] memory _hash, string[][] memory _tags) public {
for(uint256 i = 0; i < _hash.length; i++ ){
if(contentHashToAuthor[_hash[i]] == 0) {
Content memory _content = new Content({
hash: _hash[i],
tags: _tags[i][],
author: msg.sender
like: 0,
dislikes: 0,
netLikes: 0,
nonce: 0,
mapping(address => bool) usersLiked;
mapping(address => bool) usersDisliked;
timeStamp: uint64(now)
});
uint256 contentIndex = contents.push(_content) - 1;
authorToContentIndices[msg.sender].push(contentIndex);
contentHashToAuthor[_hash[i]] = msg.sender;
contentIndices[_hash[i]] = contentIndex;
} else {
revert("Content already Exist!")
}
}
}
function like(bytes32 _hash) public {
uint256 cId = contentIndex[_hash];
Content storage c = contents[cId];
if(c.usersLiked[msg.sender] != true){
c.usersLiked[msg.sender] = true;
if(c.usersDisliked[msg.sender] == true){
c.usersDisliked[msg.sender] == false;
c.dislikes--;
}
c.likes++;
c.netLikes++;
//logic for rewarding ERC777 for every 100th netLike.
//todo
if(c.netLikes == 100){
//mint function to hit with every 100th netLike
_mint(c.author, 1, "", "");
}
} else {
revert("Already liked!")
}
}
function dislike(bytes32 _hash) public {
uint256 cId = contentIndex[_hash];
Content storage c = contents[cId];
if(c.usersDisliked[msg.sender] != true){
c.usersDisliked[msg.sender] = true;
if(c.usersLiked == true){
c.usersLiked == false;
c.likes--;
c.netLikes--;
}
c.dislikes++;
c.netLikes--;
} else {
revert("Already disliked!")
}
}
You can add a counter of rewards
to the struct Content
.
struct Content{
// ... rest of your code
uint8 rewards; // Max value of uint8 is 255, which represents 25.5k netLikes. If that's not sufficient, use uint16.
}
if(c.netLikes % 100 == 0 && c.netLikes / 100 == c.rewards + 1){
//mint function to hit with every 100th netLike
_mint(c.author, 1, "", "")
c.rewards++;
}
Your original code if(c.netLikes == 100)
only works for the 1st reward (100th netLike).
The updated code:
c.netLikes % 100 == 0
Checks whether netLikes
is divisible by 100c.netLikes / 100 == c.rewards + 1
Validates that the reward hasn't been given for this 100.Example with values:
netLikes
99, likes
99, dislikes
0, rewards
0, one new like:
likes
becomes 100, netLikes
becomes 100c.netLikes % 100 == 0
=> 100 % 100 == 0
=> truec.netLikes / 100 == c.rewards + 1
=> 100 / 100 == 0 + 1
=> true_mint()
is called and rewards
becomes 1netLikes
100, likes
100, dislikes
0, rewards
1, one new dislike:
dislikes
becomes 1, netLikes
becomes 99netLikes
99, likes
100, dislikes
1, rewards
1, one new like:
likes
becomes 101, netLikes
becomes 100c.netLikes % 100 == 0
=> 100 % 100 == 0
=> truec.netLikes / 100 == c.rewards + 1
=> 100 / 100 == 1 + 1
=> false