diff --git a/contracts/CubLearn.sol b/contracts/CubLearn.sol
new file mode 100644
index 0000000..3422ed9
--- /dev/null
+++ b/contracts/CubLearn.sol
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import "@openzeppelin/contracts/access/Ownable.sol";
+import "./DTLToken.sol";
+import "./NftCertificate.sol";
+
+contract CubLearn is Ownable {
+ DTLToken dtlContract;
+ NftCertificate cubcertContract;
+
+ uint256 public cashbackPercentage;
+
+ // course id => price in DTL
+ mapping(string => uint256) private coursePrices;
+
+ // course id => student address => is enrolled
+ mapping(string => mapping(address => bool)) private enrolledCourses;
+
+ // course id => student address => is certificate issued
+ mapping(string => mapping(address => bool)) private issuedCertificates;
+
+ constructor(address dtlContractAddress, address cubcertContractAddress) Ownable(msg.sender) {
+ dtlContract = DTLToken(dtlContractAddress);
+ cubcertContract = NftCertificate(cubcertContractAddress);
+
+ coursePrices["1"] = 300;
+ coursePrices["2"] = 500;
+ coursePrices["3"] = 200;
+ cashbackPercentage = 50;
+ }
+
+ function setCashbackPercentage(uint256 newValue) external onlyOwner {
+ require(newValue <= 100, "Cashback percentage cannot be more than 100.");
+
+ cashbackPercentage = newValue;
+ }
+
+ function enroll(string memory courseId) external {
+ require(coursePrices[courseId] != 0, "Course not found.");
+
+ dtlContract.transferFrom(msg.sender, address(this), coursePrices[courseId]);
+
+ enrolledCourses[courseId][msg.sender] = true;
+ }
+
+ function finishCourse(
+ string memory courseId,
+ string memory studentFullName,
+ string memory courseName,
+ string memory instructorFullName
+ ) external {
+ require(enrolledCourses[courseId][msg.sender], "Must be enrolled in course.");
+ require(!issuedCertificates[courseId][msg.sender], "Certificate already issued.");
+
+ cubcertContract.mintCertificate(msg.sender, studentFullName, courseName, instructorFullName);
+
+ // Mark the certificate as issued
+ issuedCertificates[courseId][msg.sender] = true;
+
+ // Cashback
+ uint256 cashbackAmount = coursePrices[courseId] * cashbackPercentage / 100;
+ dtlContract.transfer(msg.sender, cashbackAmount);
+ }
+
+ function getDTLBalance() external view onlyOwner returns (uint256) {
+ return dtlContract.balanceOf(address(this));
+ }
+
+ function transferAllDTLBalanceToMe() external onlyOwner {
+ uint256 balance = dtlContract.balanceOf(address(this));
+ dtlContract.transfer(msg.sender, balance);
+ }
+}
diff --git a/contracts/DTLToken.sol b/contracts/DTLToken.sol
new file mode 100644
index 0000000..d8b2a0c
--- /dev/null
+++ b/contracts/DTLToken.sol
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
+
+contract DTLToken is ERC20 {
+ constructor(address initialHolder) ERC20("Digital Turkish Lira", "DTL") {
+ _mint(initialHolder, 1000000000);
+ }
+
+ function decimals() public view virtual override returns (uint8) {
+ return 0;
+ }
+
+ function approveMax(address spender) external returns (bool) {
+ return approve(spender, totalSupply());
+ }
+}
diff --git a/contracts/NftCertificate.sol b/contracts/NftCertificate.sol
index 9619bd6..235db56 100644
--- a/contracts/NftCertificate.sol
+++ b/contracts/NftCertificate.sol
@@ -8,100 +8,92 @@ import "@openzeppelin/contracts/utils/Base64.sol";
contract NftCertificate is ERC721 {
using Strings for uint256;
- uint256 public nextTokenId;
+ uint256 public nextTokenId;
- mapping(uint256 => CertificateInfo) private certificateInfoMapping;
+ mapping(uint256 => CertificateInfo) private certificateInfoMapping;
- // course id => student address => is cert issued
- mapping(string => mapping(address => bool)) private issuedCertificates;
+ struct CertificateInfo {
+ string studentFullName;
+ string courseName;
+ string instructorFullName;
+ }
- struct CertificateInfo {
- string studentFullName;
- string courseName;
- string instructorFullName;
- }
-
- constructor() ERC721("CubLearn Certificate", "CUBCERT") {}
-
- function mintCertificate(
- string memory courseId,
- string memory studentFullName,
- string memory courseName,
- string memory instructorFullName
- ) external {
- require(!issuedCertificates[courseId][msg.sender], "Certificate already issued.");
+ constructor() ERC721("CubLearn Certificate", "CUBCERT") {}
+ function mintCertificate(
+ address recipient,
+ string memory studentFullName,
+ string memory courseName,
+ string memory instructorFullName
+ ) external {
uint256 tokenId = nextTokenId;
-
+
_storeCertificateInfo(tokenId, studentFullName, courseName, instructorFullName);
- _safeMint(msg.sender, tokenId);
+ _safeMint(recipient, tokenId);
- // Mark the certificate as issued
- issuedCertificates[courseId][msg.sender] = true;
+ nextTokenId++;
+ }
- nextTokenId++;
- }
+ function _storeCertificateInfo(
+ uint256 tokenId,
+ string memory studentFullName,
+ string memory courseName,
+ string memory instructorFullName
+ ) internal {
+ certificateInfoMapping[tokenId] = CertificateInfo({
+ studentFullName: studentFullName,
+ courseName: courseName,
+ instructorFullName: instructorFullName
+ });
+ }
- function _storeCertificateInfo(
- uint256 tokenId,
- string memory studentFullName,
- string memory courseName,
- string memory instructorFullName
- ) internal {
- certificateInfoMapping[tokenId] = CertificateInfo({
- studentFullName: studentFullName,
- courseName: courseName,
- instructorFullName: instructorFullName
- });
- }
-
- function getCertificateInfo(uint256 tokenId)
- external
- view
- returns (
- CertificateInfo memory certInfo
- )
- {
- return certificateInfoMapping[tokenId];
- }
+ function getCertificateInfo(uint256 tokenId)
+ external
+ view
+ returns (
+ CertificateInfo memory certInfo
+ )
+ {
+ return certificateInfoMapping[tokenId];
+ }
function _getSvg(uint256 tokenId) internal view returns (string memory) {
- CertificateInfo storage certInfo = certificateInfoMapping[tokenId];
- string memory svg = string(
- abi.encodePacked(
- unicode"data:image/svg+xml;utf8,"
- )
- );
- return svg;
- }
+ CertificateInfo storage certInfo = certificateInfoMapping[tokenId];
+ string memory svg = string(
+ abi.encodePacked(
+ unicode"data:image/svg+xml;utf8,"
+ )
+ );
+ return svg;
+ }
function tokenURI(uint256 tokenId)
- external
- view
- override
- returns (string memory)
- {
- bytes memory json = abi.encodePacked(
- '{',
- '"name": "CubLearn Certificate #', tokenId.toString(), '",',
- '"image_data": "', _getSvg(tokenId), '"',
- '}'
- );
+ public
+ view
+ override
+ returns (string memory)
+ {
+ bytes memory json = abi.encodePacked(
+ '{',
+ '"name": "CubLearn Certificate #', tokenId.toString(), '",',
+ '"image_data": "', _getSvg(tokenId), '"',
+ '}'
+ );
- return string(
- abi.encodePacked(
- "data:application/json;base64,",
- Base64.encode(json)
- )
- );
- }
+ return string(
+ abi.encodePacked(
+ "data:application/json;base64,",
+ Base64.encode(json)
+ )
+ );
+ }
}