Skip to content

Instantly share code, notes, and snippets.

@max-clinch
Created February 12, 2024 21:01
Show Gist options
  • Select an option

  • Save max-clinch/e795a5e061c0a28e0eff3ac4fe72575e to your computer and use it in GitHub Desktop.

Select an option

Save max-clinch/e795a5e061c0a28e0eff3ac4fe72575e to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./LearnCoin.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract LearnAndEarnHub is Ownable {
LearnCoin public learnCoin;
mapping(address => uint256) public userStayingTime;
mapping(address => uint256) public userLoginTimestamp;
mapping(address => uint256) public stakedBalance;
mapping(address => uint256) public stakingStartTime;
mapping(address => uint256[]) public userTokens;
mapping(address => uint256) public userCorrectAnswers;
mapping(address => address) public referrers;
mapping(address => bool) public referralRewards;
mapping(address => bool) public proofOfLearning;
mapping(address => string) public userDID; // Decentralized Identity
mapping(uint256 => string) public questions;
mapping(uint256 => string) public answers;
event LoggedIn(address indexed user);
event QuestionAdded(uint256 indexed questionId, string question);
event AnswerAdded(uint256 indexed questionId, string answer);
event Staked(address indexed user, uint256 amount);
event Unstaked(address indexed user, uint256 amount, uint256 reward);
event Referred(address indexed user, address indexed referrer);
event ReferralReward(address indexed referrer, uint256 reward);
event ProofOfLearning(address indexed user);
event DecentralizedIdentitySet(address indexed user, string did);
modifier onlyValidCourse(address user, uint256 courseId) {
// Add logic to validate if the course is completed
_;
}
constructor(address learnCoinAddress) Ownable(msg.sender){
learnCoin = LearnCoin(learnCoinAddress);
}
function recordLogin() external {
userLoginTimestamp[msg.sender] = block.timestamp;
emit LoggedIn(msg.sender);
}
function getUserStayingTime(address user) external view returns (uint256) {
return block.timestamp - userLoginTimestamp[user];
}
function getAllUserTokens(address user) external view returns (uint256[] memory) {
return userTokens[user];
}
function addToken(address user, uint256 tokenId) external onlyOwner {
userTokens[user].push(tokenId);
}
function addQuestion(uint256 questionId, string memory question) external onlyOwner {
questions[questionId] = question;
emit QuestionAdded(questionId, question);
}
function addAnswer(uint256 questionId, string memory answer) external onlyOwner {
answers[questionId] = answer;
emit AnswerAdded(questionId, answer);
}
function setUserAnswer(uint256 questionId, uint256 /*userAnswer*/) external {
userCorrectAnswers[msg.sender] = questionId;
}
function getUserAnswer(uint256 /*questionId*/) external view returns (uint256) {
return userCorrectAnswers[msg.sender];
}
function checkAnswer(uint256 questionId, uint256 userAnswer) external view returns (bool) {
return keccak256(abi.encodePacked(bytes32(userAnswer))) == keccak256(bytes(answers[questionId]));
}
function stake(uint256 amount) external {
require(amount > 0, "Amount must be greater than 0");
require(learnCoin.balanceOf(msg.sender) >= amount, "Insufficient LearnCoins");
learnCoin.transferFrom(msg.sender, address(this), amount);
stakedBalance[msg.sender] += amount;
stakingStartTime[msg.sender] = block.timestamp;
emit Staked(msg.sender, amount);
}
function unstake() external {
require(stakedBalance[msg.sender] > 0, "No staked amount");
uint256 stakedAmount = stakedBalance[msg.sender];
uint256 reward = calculateStakingReward(msg.sender);
learnCoin.transfer(msg.sender, stakedAmount + reward);
stakedBalance[msg.sender] = 0;
stakingStartTime[msg.sender] = 0;
emit Unstaked(msg.sender, stakedAmount, reward);
}
function calculateStakingReward(address staker) internal view returns (uint256) {
uint256 duration = block.timestamp - stakingStartTime[staker];
return stakedBalance[staker] * duration / 86400; // Assuming 1 day as the staking duration
}
function referUser(address newUser) external {
require(newUser != address(0) && newUser != msg.sender, "Invalid referral address");
require(referrers[newUser] == address(0), "User already referred");
referrers[newUser] = msg.sender;
emit Referred(newUser, msg.sender);
}
function claimReferralReward() external {
require(referrers[msg.sender] != address(0), "No referrer for the user");
require(referralRewards[msg.sender] == false, "Referral reward already claimed");
uint256 reward = calculateReferralReward(msg.sender);
learnCoin.transfer(msg.sender, reward);
referralRewards[msg.sender] = true;
emit ReferralReward(referrers[msg.sender], reward);
}
function calculateReferralReward(address user) internal pure returns (uint256) {
uint256 reward;
if (containsDigit(uint256(uint160(user)), 5)) {
reward = 10;
} else {
reward = 5;
}
return reward;
}
// Helper function to check if a number contains a specific digit
function containsDigit(uint256 number, uint256 digit) internal pure returns (bool) {
while (number > 0) {
if (number % 10 == digit) {
return true;
}
number /= 10;
}
return false;
}
function setProofOfLearning() external onlyOwner {
proofOfLearning[msg.sender] = true;
emit ProofOfLearning(msg.sender);
}
function setDecentralizedIdentity(string memory did) external {
require(bytes(did).length > 0, "DID cannot be empty");
userDID[msg.sender] = did;
emit DecentralizedIdentitySet(msg.sender, did);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract LearnCoin is ERC20, ERC20Burnable, ERC20Pausable, Ownable {
constructor() ERC20("LearnCoin", "LC") Ownable(msg.sender) {
_mint(msg.sender, 1000000 * 10**decimals());
}
function _update(address from, address to, uint256 value) internal virtual override(ERC20, ERC20Pausable) {
super._update(from, to, value);
}
function mint(address account, uint256 amount) external onlyOwner {
_mint(account, amount);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment