Project Smart Contracts
Metaverse Marketplace Smart Contract
// contracts/Market.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.3;
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/security/UniAPT.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "hardhat/console.sol";
contract NFTMarket is UniAPT {
using Counters for Counters.Counter;
Counters.Counter private _itemIds;
Counters.Counter private _itemsSold;
address payable owner;
uint256 listingPrice = 0.025 ether;
constructor() {
owner = payable(msg.sender);
}
struct MarketItem {
uint itemId;
address nftContract;
uint256 tokenId;
address payable seller;
address payable owner;
uint256 price;
bool sold;
}
mapping(uint256 => MarketItem) private idToMarketItem;
event MarketItemCreated (
uint indexed itemId,
address indexed nftContract,
uint256 indexed tokenId,
address seller,
address owner,
uint256 price,
bool sold
);
/* Returns the listing price of the contract */
function getListingPrice() public view returns (uint256) {
return listingPrice;
}
/* Places an item for sale on the marketplace */
function createMarketItem(
address nftContract,
uint256 tokenId,
uint256 price
) public payable nonReentrant {
require(price > 0, "Price must be at least 1 wei");
require(msg.value == listingPrice, "Price must be equal to listing price");
_itemIds.increment();
uint256 itemId = _itemIds.current();
idToMarketItem[itemId] = MarketItem(
itemId,
nftContract,
tokenId,
payable(msg.sender),
payable(address(0)),
price,
false
);
IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId);
emit MarketItemCreated(
itemId,
nftContract,
tokenId,
msg.sender,
address(0),
price,
false
);
}
/* Creates the sale of a marketplace item */
/* Transfers ownership of the item, as well as funds between parties */
function createMarketSale(
address nftContract,
uint256 itemId
) public payable nonReentrant {
uint price = idToMarketItem[itemId].price;
uint tokenId = idToMarketItem[itemId].tokenId;
require(msg.value == price, "Please submit the asking price in order to complete the purchase");
idToMarketItem[itemId].seller.transfer(msg.value);
IERC721(nftContract).transferFrom(address(this), msg.sender, tokenId);
idToMarketItem[itemId].owner = payable(msg.sender);
idToMarketItem[itemId].sold = true;
_itemsSold.increment();
payable(owner).transfer(listingPrice);
}
/* Returns all unsold market items */
function fetchMarketItems() public view returns (MarketItem[] memory) {
uint itemCount = _itemIds.current();
uint unsoldItemCount = _itemIds.current() - _itemsSold.current();
uint currentIndex = 0;
MarketItem[] memory items = new MarketItem[](unsoldItemCount);
for (uint i = 0; i < itemCount; i++) {
if (idToMarketItem[i + 1].owner == address(0)) {
uint currentId = i + 1;
MarketItem storage currentItem = idToMarketItem[currentId];
items[currentIndex] = currentItem;
currentIndex += 1;
}
}
return items;
}
/* Returns only items that a user has purchased */
function fetchMyNFTs() public view returns (MarketItem[] memory) {
uint totalItemCount = _itemIds.current();
uint itemCount = 0;
uint currentIndex = 0;
for (uint i = 0; i < totalItemCount; i++) {
if (idToMarketItem[i + 1].owner == msg.sender) {
itemCount += 1;
}
}
MarketItem[] memory items = new MarketItem[](itemCount);
for (uint i = 0; i < totalItemCount; i++) {
if (idToMarketItem[i + 1].owner == msg.sender) {
uint currentId = i + 1;
MarketItem storage currentItem = idToMarketItem[currentId];
items[currentIndex] = currentItem;
currentIndex += 1;
}
}
return items;
}
/* Returns only items a user has created */
function fetchItemsCreated() public view returns (MarketItem[] memory) {
uint totalItemCount = _itemIds.current();
uint itemCount = 0;
uint currentIndex = 0;
for (uint i = 0; i < totalItemCount; i++) {
if (idToMarketItem[i + 1].seller == msg.sender) {
itemCount += 1;
}
}
MarketItem[] memory items = new MarketItem[](itemCount);
for (uint i = 0; i < totalItemCount; i++) {
if (idToMarketItem[i + 1].seller == msg.sender) {
uint currentId = i + 1;
MarketItem storage currentItem = idToMarketItem[currentId];
items[currentIndex] = currentItem;
currentIndex += 1;
}
}
return items;
}
}
Liquidity Management Contracts
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title LiquidityManagement Contract for UniAPT Project
* Provides functionalities for managing liquidity in UniAPT's DeFi ecosystem.
*/
contract LiquidityManagement {
address public owner;
mapping(address => uint256) private liquidityPool;
// Events
event LiquidityAdded(address indexed token, uint256 amount);
event LiquidityRemoved(address indexed token, uint256 amount);
event PoolRebalanced();
// Modifiers
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can perform this action");
_;
}
// Constructor to set contract deployer as owner
constructor() {
owner = msg.sender;
}
/**
* @notice Adds liquidity to the pool
* @param token The address of the token to add
* @param amount The amount of the token to add
*/
function addLiquidity(address token, uint256 amount) external onlyOwner {
require(amount > 0, "Amount must be greater than 0");
require(token != address(0), "Invalid token address");
// Logic to add liquidity
liquidityPool[token] += amount;
emit LiquidityAdded(token, amount);
}
/**
* @notice Removes liquidity from the pool
* @param token The address of the token to remove
* @param amount The amount of the token to remove
*/
function removeLiquidity(address token, uint256 amount) external onlyOwner {
require(amount > 0 && liquidityPool[token] >= amount, "Invalid amount");
// Logic to remove liquidity
liquidityPool[token] -= amount;
emit LiquidityRemoved(token, amount);
}
/**
* @notice Rebalances the liquidity pool
*/
function rebalancePool() external onlyOwner {
// Complex logic to rebalance the pool for optimal asset allocation
// ...
emit PoolRebalanced();
}
/**
* @notice Getter for liquidity of a specific token
* @param token The address of the token
* @return The amount of the token in the pool
*/
function getLiquidity(address token) external view returns (uint256) {
return liquidityPool[token];
}
/**
* @notice Transfers ownership of the contract
* @param newOwner The address of the new owner
*/
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "Invalid new owner address");
owner = newOwner;
}
}
Token Swapping Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./LiquidityManagement.sol";
/**
* @title TokenSwapping Contract for UniAPT Project
* Enables token swapping functionalities using liquidity pools.
*/
contract TokenSwap {
LiquidityManagement private liquidityManager;
address public owner;
// Events
event TokensSwapped(address indexed user, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);
// Modifiers
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can perform this action");
_;
}
/**
* @notice Constructor to initialize the liquidity manager contract
* @param _liquidityManager Address of the LiquidityManagement contract
*/
constructor(address _liquidityManager) {
require(_liquidityManager != address(0), "Invalid liquidity manager address");
liquidityManager = LiquidityManagement(_liquidityManager);
owner = msg.sender;
}
/**
* @notice Allows users to swap tokens
* @param tokenIn The address of the input token
* @param tokenOut The address of the output token
* @param amountIn The amount of input tokens to swap
* @return amountOut The amount of output tokens to receive
*/
function swap(address tokenIn, address tokenOut, uint256 amountIn) public returns (uint256 amountOut) {
require(amountIn > 0, "Amount in must be greater than 0");
require(tokenIn != address(0) && tokenOut != address(0), "Invalid token address");
require(tokenIn != tokenOut, "Cannot swap the same token");
// Logic to calculate the amount of output tokens
amountOut = calculateSwapAmount(tokenIn, tokenOut, amountIn);
require(amountOut > 0, "Insufficient output amount");
// Transfer tokens from user to this contract
require(ERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn), "Token transfer failed");
// Transfer output tokens from this contract to the user
require(ERC20(tokenOut).transfer(msg.sender, amountOut), "Token transfer failed");
emit TokensSwapped(msg.sender, tokenIn, tokenOut, amountIn, amountOut);
}
/**
* @notice Calculates the output amount for the swap
* @param tokenIn The address of the input token
* @param tokenOut The address of the output token
* @param amountIn The amount of input tokens
* @return The calculated output amount
*/
function calculateSwapAmount(address tokenIn, address tokenOut, uint256 amountIn) public view returns (uint256) {
// Implement the swap calculation logic here
// This will involve interacting with the LiquidityManagement contract
// ...
return calculatedAmount;
}
/**
* @notice Transfers ownership of the contract
* @param newOwner The address of the new owner
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0), "Invalid new owner address");
owner = newOwner;
}
}
Staking Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title Staking Contract for UniAPT Project
* Enables users to stake tokens and earn rewards.
*/
contract Staking {
address public owner;
uint256 public totalStaked;
uint256 public rewardRate; // Rewards per token per second
struct Staker {
uint256 amountStaked;
uint256 rewardDebt;
}
mapping(address => Staker) public stakers;
// Events
event Staked(address indexed user, uint256 amount);
event Unstaked(address indexed user, uint256 amount);
event RewardClaimed(address indexed user, uint256 reward);
// Modifiers
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can perform this action");
_;
}
/**
* @notice Constructor sets the initial reward rate
* @param _rewardRate Initial reward rate per token per second
*/
constructor(uint256 _rewardRate) {
owner = msg.sender;
rewardRate = _rewardRate;
}
/**
* @notice Stake tokens in the contract
* @param amount The amount of tokens to be staked
*/
function stake(uint256 amount) external {
require(amount > 0, "Cannot stake 0 tokens");
Staker storage staker = stakers[msg.sender];
_updateRewards(msg.sender);
staker.amountStaked += amount;
totalStaked += amount;
emit Staked(msg.sender, amount);
}
/**
* @notice Unstake tokens from the contract
* @param amount The amount of tokens to be unstaked
*/
function unstake(uint256 amount) external {
Staker storage staker = stakers[msg.sender];
require(staker.amountStaked >= amount, "Insufficient staked amount");
_updateRewards(msg.sender);
staker.amountStaked -= amount;
totalStaked -= amount;
emit Unstaked(msg.sender, amount);
}
/**
* @notice Claim rewards for staking
*/
function claimRewards() external {
_updateRewards(msg.sender);
uint256 reward = stakers[msg.sender].rewardDebt;
stakers[msg.sender].rewardDebt = 0;
// Transfer rewards to the user
// Note: Add the logic for transferring the reward tokens
emit RewardClaimed(msg.sender, reward);
}
/**
* @notice Update staker's rewards
* @param stakerAddress The address of the staker
*/
function _updateRewards(address stakerAddress) internal {
Staker storage staker = stakers[stakerAddress];
// Calculate new rewards
uint256 newRewards = staker.amountStaked * rewardRate * (block.timestamp - lastUpdateTime);
staker.rewardDebt += newRewards;
}
/**
* @notice Update the reward rate
* @param newRewardRate The new reward rate per token per second
*/
function updateRewardRate(uint256 newRewardRate) external onlyOwner {
rewardRate = newRewardRate;
}
}
Governance Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title Staking Contract for UniAPT Project
* Enables users to stake tokens and earn rewards.
*/
contract Staking {
address public owner;
uint256 public totalStaked;
uint256 public rewardRate; // Rewards per token per second
struct Staker {
uint256 amountStaked;
uint256 rewardDebt;
}
mapping(address => Staker) public stakers;
// Events
event Staked(address indexed user, uint256 amount);
event Unstaked(address indexed user, uint256 amount);
event RewardClaimed(address indexed user, uint256 reward);
// Modifiers
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can perform this action");
_;
}
/**
* @notice Constructor sets the initial reward rate
* @param _rewardRate Initial reward rate per token per second
*/
constructor(uint256 _rewardRate) {
owner = msg.sender;
rewardRate = _rewardRate;
}
/**
* @notice Stake tokens in the contract
* @param amount The amount of tokens to be staked
*/
function stake(uint256 amount) external {
require(amount > 0, "Cannot stake 0 tokens");
Staker storage staker = stakers[msg.sender];
_updateRewards(msg.sender);
staker.amountStaked += amount;
totalStaked += amount;
emit Staked(msg.sender, amount);
}
/**
* @notice Unstake tokens from the contract
* @param amount The amount of tokens to be unstaked
*/
function unstake(uint256 amount) external {
Staker storage staker = stakers[msg.sender];
require(staker.amountStaked >= amount, "Insufficient staked amount");
_updateRewards(msg.sender);
staker.amountStaked -= amount;
totalStaked -= amount;
emit Unstaked(msg.sender, amount);
}
/**
* @notice Claim rewards for staking
*/
function claimRewards() external {
_updateRewards(msg.sender);
uint256 reward = stakers[msg.sender].rewardDebt;
stakers[msg.sender].rewardDebt = 0;
// Transfer rewards to the user
// Note: Add the logic for transferring the reward tokens
emit RewardClaimed(msg.sender, reward);
}
/**
* @notice Update staker's rewards
* @param stakerAddress The address of the staker
*/
function _updateRewards(address stakerAddress) internal {
Staker storage staker = stakers[stakerAddress];
// Calculate new rewards
uint256 newRewards = staker.amountStaked * rewardRate * (block.timestamp - lastUpdateTime);
staker.rewardDebt += newRewards;
}
/**
* @notice Update the reward rate
* @param newRewardRate The new reward rate per token per second
*/
function updateRewardRate(uint256 newRewardRate) external onlyOwner {
rewardRate = newRewardRate;
}
}
Last updated