i want create a simple smartcontract, where initial supply is 1000 & 1000 to a specific wallet.now i want the supply of wallet(1000) to lock for a year and every month 5% of that supply should be added to initial supply.
so far i develop
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
contract Timer{
uint256 public intialSuply= 1000;
address public wallet= 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
address public owner;
mapping (address=>uint) public balances;
constructor(){
owner=msg.sender;
balances[wallet]=1000;
}
modifier onlyOwner(){
require(owner==msg.sender);
_;
}
function locker()public {
}
}
Your post explanation and the code example you've provided is very unclear. I assume you're not using the standards of ERC-20 and only need to keep track of a single parameter of initialSupply.
Check this out :
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
contract Timer{
/*
#param initialSupply : adding 18 decimals to avoid fraction
*/
uint256 public initialSupply = 1000 * (10 ** 18);
uint256 public ts_end;
address public wallet = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
address public owner;
bool public claimed;
mapping (address => uint256) public balances;
modifier onlyOwner() {
require(owner == msg.sender);
_;
}
constructor() {
owner = msg.sender;
balances[wallet] = initialSupply;
/* Assuming a year with 365-days , i.e no leep year */
ts_end = block.timestamp + (86400 * 30 * 12);
}
function claim() public onlyOwner {
require(ts_end > block.timestamp,"Can not claim yet");
require(claimed = false,"Already claimed");
claimed = true;
for(uint i = 0 ; i < 12 ; i++) {
initialSupply += (initialSupply * 15) / 100;
}
balances[wallet] = initialSupply;
}
function balanceOf() external view returns(uint256) {
return balances[msg.sender];
}
}
Related
something strange is going on. I'm testing some contracts on remix EVM. I have some pretty basic NFT staking contracts that works fine when comes to staking and transfering the token. However, if I try to execute the unstake function, the transaction gets reverted saying that the the require conditions are not passing. However, and more strange is that if I call the functions inside the require separately the condition is true!
I don't know whats going on at this point, so please any advice or help would be much appreciated. Currently I have three contracts (ERC20, ERC721, ERC721staking) with all functions working just right except for the unstake function.
These are my contracts:
Energy.sol (ERC20):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
/* Simple ERC20 token contract to issue rewards */
contract Energy is ERC20, Ownable {
mapping(address => bool) minters;
constructor() ERC20("ENERGY", "NRG") {
_mint(msg.sender, 100 * 10**decimals());
}
modifier isMinter() {
require(minters[msg.sender], "Caller is not authorized to mint!");
_;
}
function mintRewards(address to, uint256 amount) external isMinter {
_mint(to, amount * 10**decimals());
}
function addMinter(address account) public onlyOwner {
minters[account] = true;
}
}
Fuel.sol (ERC721)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
contract Fuel is ERC721, ERC721Burnable, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
constructor() ERC721("Fuel", "FUEL") {}
function safeMint(address to) public onlyOwner {
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(to, tokenId);
}
}
Generator.sol (staking):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "#openzeppelin/contracts/security/ReentrancyGuard.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "./Energy.sol";
import "./Fuel.sol";
struct Loader {
uint256[] fuelIds;
mapping(uint256 => uint256) loadBlock;
}
contract Generator is Ownable, ReentrancyGuard, IERC721Receiver {
Fuel fuel;
Energy energy;
uint256 rewardsPerBlock = 5;
mapping(address => Loader) loaders;
// Enumeration of fuelIds staked indexes of a loader
mapping(address => mapping(uint256 => uint256)) public fuelIdIndex;
// tracks owner of a fuelId
mapping(uint256 => address) public loaderOf;
constructor(address _fuel, address _energy) {
fuel = Fuel(_fuel);
energy = Energy(_energy);
}
function stake(uint256 fuelId) public nonReentrant {
// safe checks
require(
fuel.ownerOf(fuelId) == msg.sender,
"You're not the owner of this NFT"
);
// push new token to staking collection
loaders[msg.sender].fuelIds.push(fuelId);
// updates index reference of fuelId
uint256 totalFuel = loaders[msg.sender].fuelIds.length;
fuelIdIndex[msg.sender][fuelId] = totalFuel - 1;
// inits staking block
loaders[msg.sender].loadBlock[fuelId] = block.number;
// add it to reference
loaderOf[fuelId] = msg.sender;
fuel.safeTransferFrom(address(msg.sender), address(this), fuelId);
}
function unstake(uint256 fuelId) public nonReentrant {
// safe checks
require(ownedByThis(fuelId), "This fuel is not being loaded here!");
require(
_loaderOf(fuelId) == address(msg.sender),
"You haven't loaded this fuel here!"
);
uint256 lastFuelIndex = loaders[msg.sender].fuelIds.length - 1;
uint256 fuelIndex = fuelIdIndex[msg.sender][fuelId];
// swap current fuelId to last position
if (lastFuelIndex != fuelIndex) {
uint256 lastFuelId = loaders[msg.sender].fuelIds[lastFuelIndex];
loaders[msg.sender].fuelIds[fuelIndex] = lastFuelIndex; // Move the last token to the slot of the to-delete token
fuelIdIndex[msg.sender][lastFuelId] = fuelIndex; // Update the moved token's index
}
// remove the last element from mapping and array
delete fuelIdIndex[msg.sender][fuelId];
delete loaders[msg.sender].fuelIds[lastFuelIndex];
delete loaders[msg.sender].loadBlock[fuelId];
delete loaderOf[fuelId];
// Transfer back to the owner
fuel.safeTransferFrom(address(this), address(msg.sender), fuelId);
claim(fuelId);
}
function claim(uint256 fuelId) public {
// safe checks
require(ownedByThis(fuelId), "This fuel is not being loaded here!");
require(
_loaderOf(fuelId) == address(msg.sender),
"You haven't loaded this fuel here!"
);
uint256 rewardsToClaim = getPendingRewards(msg.sender, fuelId);
energy.mintRewards(msg.sender, rewardsToClaim);
loaders[msg.sender].loadBlock[fuelId] = block.number;
}
function claimAll() public nonReentrant {
// safe checks
require(
loaders[msg.sender].fuelIds.length > 0,
"You have no fuel loaded here!"
);
uint256 totalFuelLoaded = totalFuelLoadedBy(msg.sender);
for (uint256 i = 0; i < totalFuelLoaded; i++) {
uint256 fuelId = loaders[msg.sender].fuelIds[i];
claim(fuelId);
}
}
function getPendingRewards(address account, uint256 fuelId)
public
view
returns (uint256)
{
uint256 loadBlock = loaders[account].loadBlock[fuelId];
uint256 blocksElapsed = block.number - loadBlock;
return blocksElapsed * rewardsPerBlock;
}
function getAllPendingRewards() public view returns (uint256) {
uint256 totalFuelLoaded = totalFuelLoadedBy(msg.sender);
uint256 totalRewards = 0;
for (uint256 i = 0; i < totalFuelLoaded; i++) {
uint256 fuelId = loaders[msg.sender].fuelIds[i];
totalRewards += getPendingRewards(msg.sender, fuelId);
}
return totalRewards;
}
function _loaderOf(uint256 fuelId) public view returns (address) {
return loaderOf[fuelId];
}
function totalFuelLoadedBy(address account) public view returns (uint256) {
return loaders[account].fuelIds.length;
}
function generatorAddress() public view returns (address) {
return address(this);
}
function ownedByThis(uint256 fuelId) public view returns (bool) {
return address(fuel.ownerOf(fuelId)) == address(this);
}
function onERC721Received(
address operator,
address from,
uint256 fuelId,
bytes calldata data
) external override returns (bytes4) {
return this.onERC721Received.selector;
}
}
If you want to test the flow (and I hope you do) be sure to deploy first the Fuel and Energy contracts, then use the address of the contracts as constructor arguments when deploying the Generator contract. Then approveForAll the generator address in the fuel instance, mint some nfts, stake in the generator contract and try to unstake. Every function will work just fine but the unstake function.
Thanks again for any help!
Function ownedByThis takes address ownerOf(fuelId) from you Fuel contract, but after you staked your NFT in Generator.sol, now Generator.sol is owner of this NFT, and your require statement with function ownedByThis is not working. Also i added (delete loaderOf[fuelId];) to the very bottom of your Claim function. Before unstake your nft dont forget to use AddMinter funtion for address of Generator.sol contract. Hope i was useful.
Updated code below
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import "#openzeppelin/contracts/security/ReentrancyGuard.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
import "./Energy.sol";
import "./Fuel.sol";
contract Generator is Ownable, ReentrancyGuard, ERC721Holder {
Fuel fuel;
Energy energy;
struct Loader {
uint256[] fuelIds;
mapping(uint256 => uint256) loadBlock;
}
uint256 rewardsPerBlock = 5;
mapping(address => Loader) loaders;
// Enumeration of fuelIds staked indexes of a loader
mapping(address => mapping(uint256 => uint256)) public fuelIdIndex;
// tracks owner of a fuelId
mapping(uint256 => address) public loaderOf;
constructor(address _fuel, address _energy) {
fuel = Fuel(_fuel);
energy = Energy(_energy);
}
function stake(uint256 fuelId) public nonReentrant {
// safe checks
require(
fuel.ownerOf(fuelId) == msg.sender,
"You're not the owner of this NFT"
);
// push new token to staking collection
loaders[msg.sender].fuelIds.push(fuelId);
// updates index reference of fuelId
uint256 totalFuel = loaders[msg.sender].fuelIds.length;
fuelIdIndex[msg.sender][fuelId] = totalFuel - 1;
// inits staking block
loaders[msg.sender].loadBlock[fuelId] = block.number;
// add it to reference
loaderOf[fuelId] = msg.sender;
fuel.safeTransferFrom(address(msg.sender), address(this), fuelId);
}
function unstake(uint256 fuelId) public nonReentrant {
// safe checks
require(msg.sender == loaderOf[fuelId], "You are not the owner");
//require(ownedByThis(fuelId), "This fuel is not being loaded here!");
// require(
// _loaderOf(fuelId) == address(msg.sender),
// "You haven't loaded this fuel here!"
// );
uint256 lastFuelIndex = loaders[msg.sender].fuelIds.length - 1;
uint256 fuelIndex = fuelIdIndex[msg.sender][fuelId];
// swap current fuelId to last position
if (lastFuelIndex != fuelIndex) {
uint256 lastFuelId = loaders[msg.sender].fuelIds[lastFuelIndex];
loaders[msg.sender].fuelIds[fuelIndex] = lastFuelIndex; // Move the
last token to the slot of the to-delete token
fuelIdIndex[msg.sender][lastFuelId] = fuelIndex; // Update the
moved token's index
}
// remove the last element from mapping and array
delete fuelIdIndex[msg.sender][fuelId];
delete loaders[msg.sender].fuelIds[lastFuelIndex];
delete loaders[msg.sender].loadBlock[fuelId];
// Transfer back to the owner
fuel.safeTransferFrom(address(this), address(msg.sender), fuelId);
claim(fuelId);
}
function claim(uint256 fuelId) public {
// safe checks
//require(ownedByThis(fuelId), "This fuel is not being loaded here!");
require(msg.sender == loaderOf[fuelId], "You are not the owner");
// require(
// _loaderOf(fuelId) == address(msg.sender),
// "You haven't loaded this fuel here!"
// );
uint256 rewardsToClaim = getPendingRewards(msg.sender, fuelId);
energy.mintRewards(msg.sender, rewardsToClaim);
loaders[msg.sender].loadBlock[fuelId] = block.number;
delete loaderOf[fuelId];
}
function claimAll() public nonReentrant {
// safe checks
require(
loaders[msg.sender].fuelIds.length > 0,
"You have no fuel loaded here!"
);
uint256 totalFuelLoaded = totalFuelLoadedBy(msg.sender);
for (uint256 i = 0; i < totalFuelLoaded; i++) {
uint256 fuelId = loaders[msg.sender].fuelIds[i];
claim(fuelId);
}
}
function getPendingRewards(address account, uint256 fuelId) public view
returns (uint256) {
uint256 loadBlock = loaders[account].loadBlock[fuelId];
uint256 blocksElapsed = block.number - loadBlock;
return blocksElapsed * rewardsPerBlock;
}
function getAllPendingRewards() public view returns (uint256) {
uint256 totalFuelLoaded = totalFuelLoadedBy(msg.sender);
uint256 totalRewards = 0;
for (uint256 i = 0; i < totalFuelLoaded; i++) {
uint256 fuelId = loaders[msg.sender].fuelIds[i];
totalRewards += getPendingRewards(msg.sender, fuelId);
}
return totalRewards;
}
function _loaderOf(uint256 fuelId) public view returns (address) {
return loaderOf[fuelId];
}
function totalFuelLoadedBy(address account) public view returns (uint256) {
return loaders[account].fuelIds.length;
}
function generatorAddress() public view returns (address) {
return address(this);
}
// function ownedByThis(uint256 fuelId) public view returns (bool) {
// return address(fuel.ownerOf(fuelId)) == address(this);
// }
function onERC721Received(address, address, uint256, bytes memory) public
virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}
I wrote a solidity that pays ERC-20 tokens for ERC-721 NFT transactions, but it doesn't work. On purchase, you trigger the purchaseToken method. But I get an unknown error. I'm testing it on ropsten. Can you find the problem with my solidity file? I can't solve it and I'm on the verge of dying. Please advice from seniors. please.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
import "./saleNFT.sol";
contract MintNFT is ERC721Enumerable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
address owner;
// constructor
constructor() ERC721("NAME", "SYMBOL") {
owner = msg.sender;
}
SaleNFT public saleNFT;
// struct
struct tokenData {
uint256 tokenId;
string tokenURI;
uint256 tokenPrice;
}
// modifier
modifier onlyOwner {
require(msg.sender == owner, "Caller not owner");
_;
}
// mapping
mapping(uint256 => string) private _tokenURIs;
// variable
uint256 balanceLength;
function mintNftToken(string memory _tokenURI) public onlyOwner returns (uint256) {
_tokenIds.increment();
uint256 nftTokenId = _tokenIds.current();
_mint(msg.sender, nftTokenId);
_setTokenURI(nftTokenId, _tokenURI);
return nftTokenId;
}
function _setTokenURI(uint256 _tokenId, string memory _tokenURI) internal {
require(_exists(_tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[_tokenId] = _tokenURI;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
import "./mintNFT.sol";
contract SaleNFT {
MintNFT public mintNftTokenAddress;
IERC20 public currencyTokenAddress;
uint256 feePercent;
address payable feeAddress;
address owner;
// constructor
constructor(address _mintNftTokenAddress, IERC20 _currencyTokenAddress, address payable _feeAddress, uint256 _feePercent) {
mintNftTokenAddress = MintNFT(_mintNftTokenAddress);
currencyTokenAddress = _currencyTokenAddress;
feeAddress = _feeAddress;
feePercent = _feePercent;
owner = msg.sender;
}
// struct
struct Trade {
uint256 item;
uint256 price;
}
// modifier
modifier onlyOwner {
require(msg.sender == owner, "Caller not owner");
_;
}
// mapping
mapping(uint256 => Trade) public trades;
// array
uint256[] public onSaleTokenArray;
function changeFee(uint256 _feePercent , address payable _feeAddress) onlyOwner external returns (bool) {
feePercent = _feePercent;
feeAddress = _feeAddress;
return true;
}
function _pay(address from, address to, uint256 amount) internal returns (bool) {
return IERC20(currencyTokenAddress).transferFrom(from, to, amount);
}
function setForSaleNft(uint256 _tokenId, uint256 _price) public {
address tokenOwner = mintNftTokenAddress.ownerOf(_tokenId);
require(tokenOwner == msg.sender, "Caller is not token owner.");
require(_price > 0, "Price is zero or lower.");
require(trades[_tokenId].price == 0, "This token is already on sale.");
require(mintNftTokenAddress.isApprovedForAll(tokenOwner, address(this)), "token owner did not approve token.");
trades[_tokenId] = Trade({
item: _tokenId,
price: _price
});
onSaleTokenArray.push(_tokenId);
}
function purchaseToken(uint256 _tokenId) external {
uint256 price = trades[_tokenId].price;
address tokenOwner = mintNftTokenAddress.ownerOf(_tokenId);
uint256 balance = currencyTokenAddress.balanceOf(msg.sender);
uint256 premium = price * feePercent / 10000;
require(price > 0, "token not sale");
require(tokenOwner != msg.sender, "Caller is token owner.");
require((balance + premium) >= price, "Lack of balance");
require(balance >= (premium + price), "Caller sent lower than price.");
require(_pay(msg.sender, tokenOwner, price), "token transfer error for owner");
mintNftTokenAddress.safeTransferFrom(tokenOwner, msg.sender, _tokenId);
require(_pay(msg.sender, feeAddress, premium), "token transfer error for feeaddress");
trades[_tokenId].price = 0;
for(uint256 i = 0; i < onSaleTokenArray.length; i++) {
if (trades[onSaleTokenArray[i]].price == 0) {
if ((onSaleTokenArray.length - 1) != i) {
onSaleTokenArray[i] = onSaleTokenArray[onSaleTokenArray.length - 1];
}
onSaleTokenArray.pop();
}
}
}
}
I am creating a nft collection and I want the random owner to receive a percentage of the mint price with each mint. But since I need to wait for the VRF response, can't figure out how to implement randomness function and function that will send the percentage to the vrf response (random owner).
pragma solidity >=0.7.0 <0.9.0;
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
contract Sofb is ERC721Enumerable, Ownable, VRFConsumerBase {
using Strings for uint256;
string baseURI;
string public baseExtension = ".json";
uint256 public cost = 0.015 ether;
uint256 public maxSupply = 7070;
uint256 public tokenCounter;
bool public paused = false;
bool public revealed = false;
string public notRevealedUri;
bytes32 internal keyHash;
uint256 internal fee;
uint256 public randomResult = 0;
address payable giftAddress = payable(msg.sender);
uint256 giftValue = 0;
mapping(bytes32 => uint256) public requestIdToRandomNumber;
mapping(bytes32 => address) public requestIdToAddress;
mapping(bytes32 => uint256) public requestIdToRequestNumberIndex;
uint256 public requestCounter;
constructor(string memory _name, string memory _symbol, string memory _initBaseURI, string memory _initNotRevealedUri, address _vrfCoordinator, address _linkToken, bytes32 _keyHash, uint256 _fee)
VRFConsumerBase(_vrfCoordinator, _linkToken)
ERC721(_name, _symbol) {
setBaseURI(_initBaseURI);
setNotRevealedURI(_initNotRevealedUri);
keyHash = _keyHash;
fee = _fee;
}
// internal
function _baseURI() internal view virtual override returns (string memory) {
return baseURI;
}
// public
function getRandomNumber() public returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");
requestIdToAddress[requestId] = msg.sender;
requestIdToRequestNumberIndex[requestId] = requestCounter;
requestCounter += 1;
return requestRandomness(keyHash, fee);
}
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
requestIdToRandomNumber[requestId] = randomness;
uint256 requestNumber = requestIdToRequestNumberIndex[requestId];
}
function mint() public payable {
uint256 supply = totalSupply();
require(!paused);
require(supply + 1 <= maxSupply);
require(msg.value >= cost);
if (msg.sender != owner()) {
require(msg.value >= cost);
}
if (supply > 0) {
require(randomResult > 0);
giftAddress = payable(ownerOf(randomResult));
giftValue = ((supply + 1 == 5) || (supply + 1 == 10)) ? address(this).balance * 1 / 100 : msg.value * 10 / 100;
(bool success, ) = payable(giftAddress).call{value: giftValue}("");
require(success);
}
_safeMint(msg.sender, supply + 1);
getRandomNumber();
}
...
}
you should mint the token and put the mint logic inside the fulfillRandomness function, to access the data you will need i will recommend you to have an array of structs with the data you need, remember that random returns a requestId, use the request id as an index to get the stored data and then mint it, it's on you if you want to delete the data after mint the nft
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.6 < 0.9.0;
import "#chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract FundMe {
mapping(address => uint256) public addressToAmountFunded;
function fund() public payable {
uint256 minimumUSD = 30 * 10 ** 18;
require(getConversionRate(msg.value) >= minimumUSD, "You need to spend more ETH");
addressToAmountFunded[msg.sender] += msg.value;
}
function getVersion() public view returns (uint256) {
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x8A753747A1Fa494EC906cE90E9f37563A8AF630e);
return priceFeed.version();
}
address public owner;
constructor() public {
owner = msg.sender;
}
function getPrice() public view returns (uint256) {
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x8A753747A1Fa494EC906cE90E9f37563A8AF630e);
(,int256 answer,,,) = priceFeed.latestRoundData();
return uint256(answer * 10000000000);
}
function getConversionRate(uint256 ethAmount) public view returns (uint256) {
uint256 ethPrice = getPrice();
uint256 ethAmountInUsd = (ethPrice * ethAmount)/1000000000000000000;
return ethAmountInUsd;
}
function withdraw() public payable {
require(msg.sender == owner);
payable(msg.sender).transfer(address(this).balance);
}
}
I write this piece of code. I get this message every time I deploy:
"gas estimation errored with the following message - execution reverted"
I know problem is in:
function fund() public payable {
uint256 minimumUSD = 30 * 10 ** 18;
require(getConversionRate(msg.value) >= minimumUSD, "You need to spend more ETH");
addressToAmountFunded[msg.sender] += msg.value;
}
In this function I try to avoid geting value below 30$.
Can anybody help me?
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "#chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
// import "#chainlink/contracts/src/v0.8/vendor/SafeMathChainlink.sol";
contract FundMe {
// using SafeMathChainlink for uint256;
mapping(address => uint256) public addressToAmountFunded;
function fund() public payable {
// min $50
uint256 minimumUSD = 50 * 10 ** 18;
// 1gwei < $50
require(getConversionRate(msg.value) >= minimumUSD, "You need to spend more ETH!");
addressToAmountFunded[msg.sender] += msg.value;
// what the ETH -> USD conversion rate
}
function getVersion() public view returns (uint256) {
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);
return priceFeed.version();
}
function getPrice() public view returns(uint256) {
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);
(, int price,,,
) = priceFeed.latestRoundData();
return uint256(price * 10000000000);
}
// 1000000000
function getConversionRate(uint256 ethAmount) public view returns (uint256) {
uint256 ethPrice = getPrice();
uint256 ethAmountInUsd = (ethPrice * ethPrice) / 1000000000000000000;
return ethAmountInUsd;
}
function withdraw() payable public {
msg.sender.transfer(address(this).balance);
}
}
==========================================
this is my error
from solidity:
TypeError: "send" and "transfer" are only available for objects of type "address payable", not "address".
--> contracts/FundMe.sol:44:9:
|
44 | msg.sender.transfer(address(this).balance);
| ^^^^^^^^^^^^^^^^^^^
please help me