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

Staking dapp #6

Open
wants to merge 13 commits into
base: staking-dapp
Choose a base branch
from
Open
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
Binary file added .DS_Store
Binary file not shown.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.env
Binary file added backend/.DS_Store
Binary file not shown.
15 changes: 15 additions & 0 deletions backend/contracts/BUIDLToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.18;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract BUIDLToken is ERC20{
constructor(string memory name, string memory symbol) ERC20(name, symbol) {

}

function mintTokens(address to, uint256 amount) external {
_mint(to, amount);
}

}
25 changes: 22 additions & 3 deletions backend/contracts/BuidlNFT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ pragma solidity 0.8.18;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract BuidlNFT is ERC721, ERC721URIStorage {
/// @title BuidlNFT Contract
/// @author Megabyte
/// @notice This contract is used to mint NFTs and transfer them.
contract BuidlNFT is ERC721, ERC721URIStorage, ERC721Enumerable {
using Counters for Counters.Counter;

/// @dev Counter to keep track of the token Id
Expand Down Expand Up @@ -36,7 +40,7 @@ contract BuidlNFT is ERC721, ERC721URIStorage {
/// Function to mint the NFT
/// @param to Address of the receiver
/// @param uri Token URI of the NFT
function safeMint(address to, string memory uri) external onlyOwner {
function safeMint(address to, string memory uri) external {
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(to, tokenId);
Expand All @@ -52,6 +56,15 @@ contract BuidlNFT is ERC721, ERC721URIStorage {

// The following functions are overrides required by Solidity.

function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId,
uint256 batchSize
) internal override(ERC721, ERC721Enumerable) {
super._beforeTokenTransfer(from, to, tokenId, batchSize);
}

function _burn(
uint256 tokenId
) internal override(ERC721, ERC721URIStorage) {
Expand All @@ -63,4 +76,10 @@ contract BuidlNFT is ERC721, ERC721URIStorage {
) public view override(ERC721, ERC721URIStorage) returns (string memory) {
return super.tokenURI(tokenId);
}
}

function supportsInterface(
bytes4 interfaceId
) public view override(ERC721, ERC721Enumerable) returns (bool) {
return super.supportsInterface(interfaceId);
}
}
62 changes: 62 additions & 0 deletions backend/contracts/Staking.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
pragma solidity 0.8.18;


import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";

import "./BUIDLToken.sol";

contract Staking is ERC721Holder {
/// @notice NFT contract
IERC721 public buidlNFT;
//ye iss contract ke liye variable hai

/// @notice Token contract
BUIDLToken public buidlToken;
//ye iss token ke liye variable hai


/// @dev owner of the contract
address owner;

/// @notice Emission rate per second
uint256 public EMISSION_RATE = ((10 ** 18) / (uint256(1 days)));

/// @notice Staking start time
mapping(address => uint256) public tokenStakedAt;

/// @notice Token ID of the staked NFT
mapping(address => uint256) public stakeTokenId;

/// @notice Constructor
/// @param nft NFT contract address
/// @param token Token contract address
constructor(address nft, address token) {
buidlNFT = IERC721(nft);
buidlToken = BUIDLToken(token);
}
function stakeNFT(uint256 tokenId) external {
require(buidlNFT.ownerOf(tokenId) == msg.sender, "ERR:NO");
buidlNFT.safeTransferFrom(msg.sender, address(this), tokenId);
tokenStakedAt[msg.sender] = block.timestamp;
stakeTokenId[msg.sender] = tokenId;
}
function calculateReward(address staker) public view returns (uint256) {
require(tokenStakedAt[staker] != 0, "ERR:NS");
//NS : Not Staked
uint256 time = block.timestamp - tokenStakedAt[staker];
return (time * EMISSION_RATE);
}
function unStakeNFT(uint256 tokenId) external {
require(stakeTokenId[msg.sender] == tokenId, "ERR:NY");
uint256 rewardAmount = calculateReward(msg.sender);

buidlNFT.safeTransferFrom(address(this), msg.sender, tokenId);

buidlToken.mintTokens(msg.sender, rewardAmount);

delete stakeTokenId[msg.sender];
delete tokenStakedAt[msg.sender];
}
}

8 changes: 8 additions & 0 deletions backend/hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ module.exports = {
url: ALCHEMY_HTTP_URL,
accounts: [PRIVATE_KEY],
},
zkEVM : {
url: "https://rpc.public.zkevm-test.net",
accounts: [PRIVATE_KEY],
},
hermes : {
url: "https://rpc-test.h4s.dojima.network/",
accounts: [PRIVATE_KEY],
}
},
etherscan: {
apiKey: {
Expand Down
32 changes: 23 additions & 9 deletions backend/scripts/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,32 @@ async function main() {
const nft = await NFT.deploy("BuidlNFT", "BN");
await nft.deployed();
console.log("Contract address:", nft.address);
} catch (error) {
console.error(error);
}

const TOKEN = await ethers.getContractFactory("BUIDLToken");
const token = await TOKEN.deploy("BUIDLToken", "BT");
await token.deployed();
console.log("Contract address:", token.address);

const STAKING = await ethers.getContractFactory("Staking");;
const staking = await STAKING.deploy(nft.address, token.address);
await staking.deployed();
console.log("Contract address:", staking.address);

console.log("Sleeping.....");
await sleep(40000);
// await sleep(60000);

try {
await hre.run("verify:verify", {
address: nft.address,
constructorArguments: ["BuidlNFT", "BN"],
});
// await hre.run("verify:verify", {
// address: nft.address,
// constructorArguments: ["BuidlNFT", "BN"],
// });
// await hre.run("verify:verify", {
// address: token.address,
// constructorArguments: ["BUIDLToken", "BT"],
// });
// await hre.run("verify:verify", {
// address: staking.address,
// constructorArguments: [nft.address, token.address],
// });
} catch (error) {
console.error(error);
}
Expand Down
126 changes: 0 additions & 126 deletions backend/test/Lock.js

This file was deleted.

35 changes: 35 additions & 0 deletions backend/test/deploy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const hre = require("hardhat");
const { expect } = require("chai");

describe("Staking Contract Deployment", function () {
it("Should deploy the Staking Contract", async function () {
const [owner, user1] = await hre.ethers.getSigners();

const NFT = await ethers.getContractFactory("BuidlNFT");
const nft = await NFT.deploy("BuidlNFT", "BN");
await nft.deployed().then((val) => {
console.log("NFT Contract Deployed");
console.log("Contract Address: " + nft.address);
});

const TOKEN = await ethers.getContractFactory("BUIDLToken");
const token = await TOKEN.deploy("BuidlToken", "BT");
await token.deployed().then((val) => {
console.log("Token Contract Deployed");
console.log("Contract Address: " + token.address);
});

const STAKING = await ethers.getContractFactory("Staking");
const staking = await STAKING.deploy(nft.address, token.address);
await staking.deployed().then((val) => {
console.log("Staking Contract Deployed");
console.log("Contract Address: " + staking.address);
});

expect(await staking.buidlToken()).to.be.equal(token.address);
expect(await staking.buidlNFT()).to.be.equal(nft.address);
});
});



1 change: 1 addition & 0 deletions frontend/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NEXT_PUBLIC_WEB3_PROJECT_ID = "1740de631ccbc46ed8fd2401056d6b85"
5 changes: 3 additions & 2 deletions frontend/ABIs/BuidlNFT.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"address": "",
"abi": []
"address": "0x3C591565694fE23bD0FeB2cCB38A35a1Db06517A",
"abi" : [{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"string","name":"uri","type":"string"}],"name":"safeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]
}

Loading