Let say there is a BEP20 token (tokenA)on the blockchain with an internal function _burn and a total supply of 100000000 token i want to write a new Smart contract that can burn token TokenA and substract from the supply how can i proceed? I've tried many solutions but still unable to call the function_burn
Since the function is internal, it means it can only be accessed internally within the contract itself or in contracts deriving from it.
You can either use ERC20Burnable extension (link below) or implement the _burn function inside your token contract with external/public modifier. This way, other contracts can call the function.
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/ERC20Burnable.sol
ERC20Burnable version:
Token contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
contract BurnMe is ERC20, ERC20Burnable {
constructor() ERC20("Burn me", "BURN"){}
function mint() external {
_mint(msg.sender, 10000);
}
}
Burning contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
contract BurnOther{
ERC20Burnable _token;
constructor(address token_){
_token = ERC20Burnable(token_);
}
function burnOther(uint256 amount) external {
_token.burnFrom(msg.sender, amount);
}
}
Your contract version:
Token contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract BurnMe is ERC20 {
constructor() ERC20("Burn me", "BURN"){}
function mint() external {
_mint(msg.sender, 10000);
}
function burn(address account, uint256 amount) external {
_spendAllowance(account, _msgSender(), amount);
_burn(account, amount);
}
}
Burning contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./burn.sol";
contract BurnOther{
BurnMe _token;
constructor(address token_){
_token = BurnMe(token_);
}
function burnOther(uint256 amount) external {
_token.burn(msg.sender, amount);
}
}
Decreasing supply is already implemented inside _burn function, so no need to worry about that. https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol#L290
Keep in mind that the burning contract needs allowance to spend the owner's tokens. You can do that by using approve function of the token contract with the burning contract's address as the parameter:
While deploying the burning contract, make sure to add the token address as the constructor parameter.
Related
I have UUPS erc721 contract. I have deployed them. Now I have a proxy contract and a logic contract.
Lets say logic contract has address 0x1234
I want a factory contract to deploy multiple upgradeable proxies by copying a already deployed proxy from blockchain and all those proxies using logic contract at address 0x1234.
I want the project to be like as shown in the figure.
I have tried the following code but it does not produce the expected result. Proxy is not initialized/Deployed :
My ERC721 contract takes ownerAddress, name and symbol as initializer arguments. ERC721 is upgradeable so it uses a initializer and not a constructor.
pragma solidity 0.8.15;
import "./GenericERC721.sol";
import "./cloneFactory.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
contract GenericFactory is Ownable, CloneFactory {
address public proxyAddress;
address public logicAddress;
address[] public addressBook;
event GenericERC721created(address deployedProxyAddress);
constructor(address _proxyAddress, address _logicAddress) {
proxyAddress = _proxyAddress;
logicAddress =_logicAddress;
}
function createProxy(
address _owner,
string calldata _name,
string calldata _symbol
) public onlyOwner {
address clone = createClone(proxyAddress);
ERC1967Proxy(clone).constructor(logicAddress, abi.encodeWithSignature("initialize(address,string,string)", _owner, _name, _symbol));
addressBook.push(clone);
emit GenericERC721created(clone);
}
}
I am testing this code on Remix:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "#chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract PriceConsumerV3 {
AggregatorV3Interface internal priceFeed;
/**
* Network: Kovan
* Aggregator: ETH/USD
* Address: 0x9326BFA02ADD2366b30bacB125260Af641031331
*/
constructor() {
priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);
}
/**
* Returns the latest price
*/
function getLatestPrice() public view returns (int) {
(
uint80 roundID,
int price,
uint startedAt,
uint timeStamp,
uint80 answeredInRound
) = priceFeed.latestRoundData();
return price;
}
}
Compilation and deployment seem to be executed correctly, however I receive this error:
call to PriceConsumerV3.getLatestPrice errored: Returned error: VM
Exception while processing transaction: revert
Any suggestion?
I've seen this error when deploying to the Javascript VM
It's due to the contract you are trying to call not being available on the VM you are using. You'll need to switch to the Injected Web3 option.
The deployment will also require having a wallet set up as you interact with an actual blockchain. The example you reference is using the Kovan Testnet.
Here are a few other links for reference
Metamask
Faucet if you need ETH
I'm trying to call claimItem function on my ERC721 token. This function basically calls _safeMint() function from OpenZeppelin ERC721 contract. Here is the question. As a first step I managed deploy a contract on polygon mumbai testnet and I can see my contract on polygon scan. But when I tried to call claimItem function, inside a Transaciton Transaction(from:EthereumAddress.fromHex(session!.accounts[0]) ,to:EthereumAddress.fromHex("CONTRACT_ADDRESS"), data: bytes); like this. Transaction completes but NFT is not minted.
Here Are Some Scree Shots
This one is from a successful one (This is deployed and minted with truffle & web3)
This one is from unsuccessful one (This is signed by MetaMask)
I don't know what I'm doing wrong and I'm really new into blockchain.
EDIT Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/utils/Counters.sol";
contract ArtItemNew is ERC721, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
using Strings for uint256;
// Optional mapping for token URIs
mapping(uint256 => string) private _tokenURIs;
constructor(string memory _tokenName, string memory _tokenSymbol) ERC721(_tokenName, _tokenSymbol) public {
}
function _setTokenURI(uint256 tokenId, string memory _tokenURI)
internal
virtual
{
require(
_exists(tokenId),
"ERC721Metadata: URI set of nonexistent token"
);
_tokenURIs[tokenId] = _tokenURI;
}
function claimItem(string memory tokenURI) public returns (uint256) {
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(msg.sender, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
}
I'm fresh on solidity, when I use remix to test my contract, I want to transfer some eth from my account to the smart contract. I have tried this code, but it seems to transfer the eth from the contract but not my account.
function addStaker (uint _stakeAmount) public membership(master, msg.sender) returns(bool) {
if(!members[msg.sender].alreadyExist) {
Member memory newMember = Member(msg.sender, true);
members[msg.sender] = newMember;
bool sent = payable(address(this)).send(_stakeAmount);
require(sent, "invalid balance");
return true;
} else {
return false;
}
}
How could I transfer eth from my account to the smart contract?
A smart contract is not able to pull a contract-specified amount of ETH from an address. The amount needs to always be specified and signed by the sender.
The contract can only validate the sent amount:
function addStaker() public payable {
require(msg.value == 1 ether);
}
How to chose the amount depends on the wallet software you're using. In case of Remix, there's the "Value" input in the "Deploy & Run Transactions" tab, where you specify the amount of ETH sent with the transaction.
If you want to implement a defi contract (since your function name is addStaker) that accepts staked coins from ERC20 tokens, the implementation is different. But if you just want to send money to contract from your metamask account, you have to mark the function payable.
function pay() public payable {
// msg.value is the amount of wei sent with the message to the contract.
// with this you are setting a minimum amount
require(msg.value > .01 ether);
// add your logic
}
I am using the below code in solidity to transfer ether from one account to another.
I am calling this from the owner's account.
But my ether gets deducted from owners and goes to contract address instead of the receiver/payee account.
function PayCredit(address payable payee, uint money, uint invoiceNum) public payable{
require(msg.sender==owner, "only owner can invoke it");
payee.transfer(address(this).balance);
claims[payee][invoiceNum].isPayed = true;
}
You are sending your ether's to contract address , change address(this) to address .
I would suggest you good practice of sending ether's to other account. Solidity transaction support value as argument and this is good place for sending ether(WEI) to other account . below code snippet will send 12 WEI to other account.
pragma solidity >=0.4.22 <0.6.0;
contract AB {
uint256 num1;
address owner;
constructor() public{
owner = msg.sender;
}
function sendBal(address payable receiver) payable external onlyOwner {
uint256 amount = msg.value;
receiver.transfer(amount);
}