Skip to content

Instantly share code, notes, and snippets.

@ahmedali8
Created November 5, 2022 06:28
Show Gist options
  • Save ahmedali8/80ef53fbd4084cbe81e6d23a1bd584f6 to your computer and use it in GitHub Desktop.
Save ahmedali8/80ef53fbd4084cbe81e6d23a1bd584f6 to your computer and use it in GitHub Desktop.
Blockchain Genesis - Web3Disrupt Workshop
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { CoffeeMock } from "./Coffee_NFT.sol";
contract Coffee {
struct Donate {
uint256 tokensDonated;
uint256 noOfDonations;
}
/*//////////////////////////////////////////////////////////////
STATE VARIABLES
//////////////////////////////////////////////////////////////*/
IERC20 public token;
CoffeeMock public nft;
uint256 public priceOfCoffee;
address payable public owner;
mapping(address => Donate) private _donations;
/*//////////////////////////////////////////////////////////////
MODIFIERS
//////////////////////////////////////////////////////////////*/
modifier onlyOwner() {
require(msg.sender == owner, "Revert: not an owner");
_;
}
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Withdrawal(uint256 tokenAmount, uint256 when);
event Deposit(uint256 amount, address sender);
event SetPriceOfCoffee(uint256 prevPriceOfCoffee, uint256 newPriceOfCoffee);
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
uint256 _priceOfCoffee,
address _erc20,
address _erc721
) {
priceOfCoffee = _priceOfCoffee;
token = IERC20(_erc20);
nft = CoffeeMock(_erc721);
owner = payable(msg.sender);
}
/*//////////////////////////////////////////////////////////////
EFFECT FUNCTIONS
//////////////////////////////////////////////////////////////*/
/**
* @notice User can call this function to donate tokens equivalent
* to number of coffees to the owner.
* @dev User must have tokens to donate.
*/
function donate(uint256 _numOfCoffees) external returns (bool) {
require(_numOfCoffees > 0, "Revert: bro donate 1 coffee atleast!");
// loading state variable in memory for gas optimization
uint256 _priceOfCoffee = priceOfCoffee;
// multiply number of coffees to donate by price of coffee
// to get total donation
uint256 _noOfTokensToDonate = _priceOfCoffee * _numOfCoffees;
// save the token balance in a local variable
uint256 _tokenBalance = token.balanceOf(msg.sender);
// check if balance is greater then the donation amount
require(_tokenBalance > _noOfTokensToDonate, "Revert: bro you're broke as well!");
// updating state
_donations[msg.sender].tokensDonated += _noOfTokensToDonate;
_donations[msg.sender].noOfDonations += 1;
// approval must be given from msg.sender to this contract address before
// transfers tokens from msg.sender to this contract
token.transferFrom(msg.sender, address(this), _noOfTokensToDonate);
for (uint256 i; i < _numOfCoffees; i++) {
// mint nft to msg.sender
nft.mintTo(msg.sender);
}
emit Deposit(_noOfTokensToDonate, msg.sender);
return true;
}
/**
* @notice Owner can withdraw tokens in the contract
* @dev Only callable by owner
*/
function withdraw() external onlyOwner returns (bool) {
// save the token balance in a local variable
uint256 _balance = token.balanceOf(address(this));
// check if tokens exist in this contract
require(_balance > 0, "Revert: No tokens in contract!");
// transfer tokens in the contract to owner
token.transfer(owner, _balance);
emit Withdrawal(_balance, block.timestamp);
return true;
}
/**
* @notice Owner can set price of coffee
* @dev Only callable by owner
*/
function setPriceOfCoffee(uint256 _priceOfCoffee) external onlyOwner {
emit SetPriceOfCoffee(priceOfCoffee, _priceOfCoffee);
priceOfCoffee = _priceOfCoffee;
}
/*//////////////////////////////////////////////////////////////
VIEW/PURE FUNCTIONS
//////////////////////////////////////////////////////////////*/
/**
* @notice Returns info of `_user`
*/
function getUserDetails(address _user)
external
view
returns (
uint256,
uint256
)
{
return (
_donations[_user].tokensDonated,
_donations[_user].noOfDonations
);
}
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol
)
ERC20(_name, _symbol)
{
// Mint 100 tokens to msg.sender
// Similar to how
// 1 dollar = 100 cents
// 1 token = 1 * (10 ** decimals)
uint8 _decimals = decimals();
uint256 _typeCastedDecimals = uint256(_decimals);
_mint(
msg.sender, // account
10_000 * 10 ** _typeCastedDecimals // amount e.g. 10_000 x 10^18
);
}
/*//////////////////////////////////////////////////////////////
EFFECT FUNCTIONS
//////////////////////////////////////////////////////////////*/
/**
* @dev Mints a new MyToken tokens of amount `_amount` to address `_to`
* @notice This is not a production ready function as anyone can mint tokens
* Only for demo purposes
*/
function mint(address _to, uint256 _amount) external {
_mint(_to, _amount);
}
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract CoffeeMock is ERC721 {
/*//////////////////////////////////////////////////////////////
STATE VARIABLES
//////////////////////////////////////////////////////////////*/
// the current NFT ID tracker
// be default value is 0
uint256 private _currentTokenId;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol
) ERC721(_name, _symbol) {}
/*//////////////////////////////////////////////////////////////
EFFECT FUNCTIONS
//////////////////////////////////////////////////////////////*/
/**
* @dev Mints a new Coffee NFT to address `to`
* @notice This is not a production ready function as anyone can mint an nft
* Only for demo purposes
*/
function mintTo(address _to) external {
// increment the token id
_currentTokenId++;
// get the incremented new token id
uint256 _id = _currentTokenId;
_safeMint(_to, _id);
}
/*//////////////////////////////////////////////////////////////
VIEW/PURE FUNCTIONS
//////////////////////////////////////////////////////////////*/
/**
* @dev Returns the current token id
* @return uint256 for the current token ID
*/
function currentTokenId() external view returns (uint256) {
return _currentTokenId;
}
/**
* @inheritdoc ERC721
*/
function tokenURI(uint256 tokenId) public view override returns (string memory) {
_requireMinted(tokenId);
// https://{cid}.ipfs.nftstorage.link/
return "ipfs://bafkreidtzux4ez453colsi2vafe6ylskwze5ybbcogjdtnasp6erdamota";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment