Burn to mint solidity - solidity

Ok so I have an issue and I'm not even sure where to begin. I NEED a burn to mint function within a smart contract for an erc20 token. It's on a 1:1 ratio version 1 for version 2. All that I've seen in my 4 hours of searching is more or less websites or dapps that do the transfer when a wallet is attached. Thank you for your time .

Not possible unless the version 1 already implements its part.
In the example below:
Deploy Version1
Deploy Version2, passing it the Version1 address
Pass the Version2 address to Version1 function setVersion2Address()
Verify the deployer token balances using the balanceOf() function on both contracts - the deployer now has 1000 tokens of Version1 and 0 tokens of Version2
Invoke burnToMint() on Version2, passing it the 1000 tokens as arguments
Verify the deployer token balances using the balanceOf() function on both contracts - the deployer now has 0 tokens of Version1 and 1000 tokens of Version2
pragma solidity ^0.8;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract Version1 is ERC20, Ownable {
address version2;
modifier onlyVersion2 {
require(msg.sender == version2);
_;
}
constructor() ERC20("Version 1", "v1") {
_mint(msg.sender, 1000);
}
function setVersion2Address(address _version2) external onlyOwner {
version2 = _version2;
}
function version2Burn(address from, uint256 amount) external onlyVersion2 {
_burn(from, amount);
}
}
contract Version2 is ERC20 {
Version1 version1;
constructor(Version1 _version1) ERC20("Version 2", "v2") {
version1 = _version1;
}
function burnToMint(uint256 amount) external {
version1.version2Burn(msg.sender, amount);
_mint(msg.sender, amount);
}
}

Related

how to make onRecivedERC20 function?

I would like to make a function for receiving ERC20 in contract and after receiving ERC20 token it should transfer that ERC20 to another wallet.
the flow should be if a user uses that function first it should send that ERC20 to the contract and after that contract should forward that token to another wallet. I don't know where to start from
example transaction is this:
https://polygonscan.com/tx/0x88d85e4b746b65708a38b8f4c5d5bc0f73ff78e28868084eed565976b46df10e
The ERC-20 standard doesn't define how to notify a receiver contract about the incoming transfer. So you'll need to use either another standard (e.g. ERC-777) or build a custom notification hook.
Here's an example of such custom notification. It builds on top of the OpenZeppelin ERC-20 implementation, checks if the receiver is a contract - and if it is a contract, tries to call its onERC20Receive() function.
You can test it by deploying two separate contracts - MyToken and SomeReceiver - and then sending tokens from the deployer address to SomeReceiver. You can see that the ReceivedTokens event was emitted, as a result of invoking the function onERC20Receive when SomeReceiver received the tokens.
pragma solidity ^0.8.16;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor() ERC20("MyToken", "MyT") {
_mint(msg.sender, 1000 * 1e18);
}
function _afterTokenTransfer(address from, address to, uint256 amount) internal override {
if (to.code.length > 0) {
// token recipient is a contract, notify them
try IERC20Receiver(to).onERC20Receive(from, amount) returns (bool success) {
// the recipient returned a bool, TODO validate if they returned true
} catch {
// the notification failed (maybe they don't implement the `IERC20Receiver` interface?)
}
}
}
}
interface IERC20Receiver {
function onERC20Receive(address from, uint256 amount) external returns (bool);
}
contract SomeReceiver is IERC20Receiver {
event ReceivedTokens(address from, uint256 amount);
function onERC20Receive(address from, uint256 amount) external returns (bool) {
emit ReceivedTokens(from, amount);
return true;
}
}

How do I accept an ERC20 token for Nft mint payment instead of ETH

How do I accept an ERC 20 token for minting NFTS on my smart contract. I’m currently paying for the minting using ETH, and I will like to accept another ERC 20 token.
You can change your mint function in order to accept the preferred token type as payment. And in order to prevent paying gas in eth, you can use biconomy forward.Check out their docs.
https://docs.biconomy.io/products/enable-paying-gas-in-erc20
You need a reference from the NFT contract to your token contract.
Let's say we have these two contracts: NFTContract, TokenContract.
contract NFTContract {
TokenContract tokenContract;
...
mint() {
tokensContract.transfer(msg.sender(), addressReceiver, tokensToSend);
...
}
}
contract TokenContract {
transfer(sender, receiver, balance) {}
}
You can check an example of how I did this in my repo I'm developing for my thesis.
https://github.com/NickVanzo/Contracts_For_Thesis
Maybe it will work for you but be careful you can take errors for solidity versions.
pragma solidity ^0.8.9;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract LSTNFT is ERC721, ERC721Burnable, Ownable {
uint256 public cost;
uint256 maxSupply = 20;
uint256 maxMintAmountPerTx = 2;
// address of the ERC-20 contract
address public erc20Contract = "ERC-20 address is here";
// instance of the ERC-20 contract
ERC20 public erc20;
constructor() ERC721("Lestonz NFT", "LSTN") {
erc20 = ERC20(erc20Contract);
}
function _baseURI() internal pure override returns (string memory) {
return "ipfs://your ipfs url";
}
modifier mintPriceCompliance(uint256 _mintAmount) {
if (msg.sender != owner()) {
require(msg.value >= cost * _mintAmount, 'Insufficient funds!');
}
_;
}
function mint(uint256 _mintAmount) public payable mintPriceCompliance(_mintAmount) {
require(erc20.balanceOf(msg.sender) >= msg.value, "Not enough ERC-20 tokens");
_safeMint(_msgSender(), _mintAmount);
}
function setCost(uint256 _cost) public onlyOwner {
cost = _cost;
}
}

Solidity calling contract with elevated permissions

I have two contracts, one for handling staking and one for minting a NFT. The flow I want is for the user to stake in frontend react app which will invoke the staking contract. The user will then be eligible to mint a NFT when staked.
Now the issue I am facing is that because the minting role is called from stakingExample contract, which requires the user to invoke this, but as it has a critical function (mint) of the other contract, it should be protected with permissions such that only StakingExample can call NFTExample contract.
Is there a way to allow the user to run NFTExample with elevated permissions temporary in smart contract?
Example of staking contract:
// SPDX-License-Identifier: unlicensed
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/access/AccessControl.sol";
import "#openzeppelin/contracts/token/ERC20/IERC20.sol";
import "#openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract StakingExample is AccessControl {
bytes32 public constant CONTRACT_ROLE = keccak256("CONTRACT_ROLE");
NFTExample public _NFTExample;
...
function someStakingFunction() {
// code that stakes and
// set some variable that tracks if user have minted
}
function claimNFT(uint256 _pid, string memory _tokenURI) public onlyRole(CONTRACT_ROLE) {
// checks if user have unclaimed NFT
if (haveUnclaimed) {
_NFTExample.mintItem(msg.sender, _tokenURI)
}
}
}
Example of NFT contract:
// SPDX-License-Identifier: unlicensed
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/access/AccessControl.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
contract CMRGachaSeedNFT is ERC721URIStorage, AccessControl, ERC721Enumerable {
bytes32 public constant CONTRACT_ROLE = keccak256("CONTRACT_ROLE");
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
...
// Only Contract Role can call mint item, which mint item and transfers it to user's address
function mintItem(address _address, string memory _tokenURI)
public
onlyRole(CONTRACT_ROLE)
returns (uint256)
{
// Do some checks
// Mint
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(_address, newItemId);
_setTokenURI(newItemId, _tokenURI);
return newItemId;
}
}
You need to add one function in staking contract which shows amount of the staking:
function showStakeAmount() external view returns(uint256){
//I don't know your codes about this but you need a mapping to store
//the stake amount of each user and here you return it but something like this:
return StakingAmountOfUsers(msg.sender);
}
Then you need an interface of the staking contract and its address, also make an modifier in NFT contract (Following changes must be added):
interface StakingInterface{
function showStakeAmount() external view returns(uint256);
}
contract CMRGachaSeedNFT is ERC721URIStorage, AccessControl, ERC721Enumerable {
uint256 AmountThatShouldBeStaked;
StakingInterface StakingContract;
constructor(address STAKING_CONTRACT_ADDRESS){
StakingContract = StakingInterface(STAKING_CONTRACT_ADDRESS);
}
modifier isStaked(){
require(StakingContract.showStakeAmount() > AmountThatShouldBeStaked, "You did not stake enough amount of X token");
_;
}
function mintItem(address _address, string memory _tokenURI)
public
onlyRole(CONTRACT_ROLE)
returns (uint256)
isStaked()
{
//Continue coding...
}
}

How to send ETH directly from ERC721 (OpenZeppelin) contract to the PaymentSplitter contract?

I have an openZeppelin ERC721 NFT contract (MyNFTPrice.sol) and also a separate PaymentSplitter contract. My understanding is that these two contract need to be deployed separately. My question is, how do I send the price of minting from my NFT contract (MyNFTPrice.sol) to the PaymentSplitter contract? Currently, the price for minting an NFT resides in the MyNFTPrice.sol contract address.
MyNFTPrice.sol
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract MyNFTPrice is ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor() public ERC721("MyNFTPrice", "NFTPRICE") {}
// Mint new NFT
function mintNFT(address recipient, string memory tokenURI) public payable {
require(msg.value >= 50000000000000000, "You need 0.05 ETH to mint the NFT");
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(recipient, newItemId);
_setTokenURI(newItemId, tokenURI);
}
}
You can use the transfer() member of the address payable.
function mintNFT(address recipient, string memory tokenURI) public payable {
require(msg.value >= 50000000000000000, "You need 0.05 ETH to mint the NFT");
// effectively redirects the `msg.value` to the `0x123` address
payable(address(0x123)).transfer(msg.value);
// ... rest of your code
}
Replace the 0x123 to the real address of the PaymentSplitter.
You can also store the address in a variable and change it when you need to. In this case, it's recommended to use an authorization mechanism, such as the Ownable pattern, so that only an authorized sender can change the value.
Since the PaymentSplitter is a contract, it needs to contain the receive() or fallback() payable function. Otherwise the PaymentSplitter as the receiver would reject the incoming payment and effectively cause the whole mintNFT() transaction to revert.
contract PaymentSplitter {
receive() external payable {
// can be empty
}
}

Remove unstrusted token from ERC20 Smart Contract

I have a question and I try to google without much existence.
Let's take the example of this token:
1inch Token
So you can see that it has different tokens that people have sent to that address.
If I were the owner, how could I implement a function to withdraw all those tokens to my wallet?
Your contract can define the ERC20 interface function transfer(), and then execute this function on the external token contract.
pragma solidity ^0.8;
interface IERC20 {
function transfer(address _to, uint256 _amount) external returns (bool);
}
contract MyContract {
modifier onlyOwner {
require(msg.sender == address(0x123), 'Not authorized');
_;
}
function withdrawERC20Token(address _tokenContractAddress, uint256 _amount) external onlyOwner {
IERC20 token = IERC20(_tokenContractAddress);
// transfer the `_amount` of tokens (mind the decimals) from this contract address
// to the `msg.sender` - the caller of the `withdrawERC20Token()` function
bool success = token.transfer(msg.sender, _amount);
require(success, 'Could not withdraw');
}
}