Created
February 12, 2024 21:01
-
-
Save max-clinch/e795a5e061c0a28e0eff3ac4fe72575e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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