I would like to use both ERC721URIStorage for setting token URI easily but I would also like the methods in ERC721Enumberable to fetch the number of tokens made by an address.
I get this error when trying to use both :
Derived contract must override function "_beforeTokenTransfer". Two or more base classes define function with same name and parameter types.
Derived contract must override function "_burn". Two or more base classes define function with same name and parameter types.
Derived contract must override function "supportsInterface". Two or more base classes define function with same name and parameter types.
Derived contract must override function "tokenURI". Two or more base classes define function with same name and parameter types.
is this just not possible at all or is there a way to Override the duplicated functions?
Below code overrides the overlapping functions from the two extensions
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
contract NameOfContract is ERC721URIStorage, ERC721Enumerable {
// Contract Code ....
function _beforeTokenTransfer(address from, address to, uint256 tokenId)
internal
override(ERC721, ERC721Enumerable)
{
super._beforeTokenTransfer(from, to, tokenId);
}
function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
Update
_beforeTokenTransfer has a new parameter and argument
Now it is like
function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize)
internal
override(ERC721, ERC721Enumerable)
{
super._beforeTokenTransfer(from, to, tokenId, batchSize);
}
Related
I'm trying to make a dynamic rule builder in solidity, I have a role manager contract that looks like so:
import "#openzeppelin/contracts/access/Ownable.sol";
// The Ownable contract to manage the contract owner
contract RoleManager is Ownable {
mapping(bytes32 => function(bytes32, address, address[] memory, uint256[] memory, bytes[] memory, string memory) external view returns (bool)) public rules;
// Set the rule for the given role
function setRule(bytes32 role, function(bytes32, address, address[] memory, uint256[] memory, bytes[] memory, string memory) external view returns (bool) rule) public onlyOwner {
rules[role] = rule;
}
//...
}
Maybe my understanding of what function parameter is wrong, I would like to build a dynamic function, How to I generate a function on ethers to pass to this ?
Use interface :
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "#openzeppelin/contracts/access/Ownable.sol";
interface IRule {
function rule (bytes32 data, address addr,
address[] memory addrArr, uint256[] memory uintArr,
bytes[] memory dataArr, string memory str)
external view returns (bool);
}
contract Demo is Ownable {
mapping(bytes32 => IRule) public rules;
function setRule(bytes32 role, IRule rule) public onlyOwner {
rules[role] = rule;
}
}
I am learning how to write a smart contract for NFT collections and the following is the example function given by the tutorial I read:
function _burn(uint256 tokenId) internal virtual override {
super._burn(tokenId);
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
}
I recognise that this function will not remove the token from the blockchain entirely. Instead, it will remove the URI of the token (regardless of who owns it). As a result, the token will still in the collection and be displayed on trading platforms, but the metadata will be gone (but it may take time to be in effect as platforms are not refreshing metadata frequently).
I wonder if this is the right practice for burn function. It would be greatly helpful for me if someone can provide me an example of how burn function is achieved on other NFT smart contracts.
Here is the easiest way to add burn function to an NFT.
GO to Openzepplin Wizard
Click ERC721
Give your token a name and symbol.
Click on mintable and burnable, and you would get mintable and burnable NFT token contract.
Here is a sample:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract MyToken is ERC721, ERC721Burnable, Ownable {
constructor() ERC721("MyToken", "MTK") {}
function safeMint(address to, uint256 tokenId) public onlyOwner {
_safeMint(to, tokenId);
}
}
The corresponding OZ wizard interface would look like this:
You would get the following public burn function:
From Openzepplin ERC721 burnable contract
Update
You can make the contract both enumarable and burnable:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract MyToken is ERC721, ERC721Enumerable, ERC721Burnable, Ownable {
constructor() ERC721("MyToken", "MTK") {}
function safeMint(address to, uint256 tokenId) public onlyOwner {
_safeMint(to, tokenId);
}
// The following functions are overrides required by Solidity.
function _beforeTokenTransfer(address from, address to, uint256 tokenId)
internal
override(ERC721, ERC721Enumerable)
{
super._beforeTokenTransfer(from, to, tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
I have two contracts in Solidity like so (based upon a tutorial):
pragma solidity >=0.4.16 <0.9.0;
contract ERC20Token {
string public name;
mapping(address => uint) public balances;
function mint() public {
balances[tx.origin]++;
}
}
contract MyContract {
address payable wallet;
address public token;
constructor(address payable _wallet, address _token) {
wallet = _wallet;
token = _token;
}
function buyToken() public payable {
ERC20Token _token = ERC20Token(address(token));
_token.mint();
wallet.transfer(msg.value);
}
}
My question is why they use ERC20Token _token = ERC20Token(address(token)); in order to access the class and call he .mint() function.
My base reflex would be to do the following instead:
ERC20Token _token = new ERC20Token();
_token.mint();
This is because the ERC20Token contract does not have a constructor, so I'm unsure where the RC20Token(address(token)) constructor parameters come from.
The new ERC20Token() expression deploys a new ERC20Token contract and returns its (newly deployed) address.
Since your ERC20Token doesn't have any constructor (and constructor params), you don't need to pass any params. But if it did have constructor params, you'd need to pass them. Example:
contract ERC20Token {
constructor (string memory _name, string memory _symbol) {
}
}
address deployedTo = new ERC20Token("MyToken", "MyT");
The ERC20Token _token = ERC20Token(<address>) creates a helper object allowing the _token to be treated as a contract implementing the ERC20Token interface, so you can execute and call its public and external functions.
It's the address of the external contract that you're passing - not the constructor params.
contract ERC20Token {
function mint() public {
}
}
ERC20Token _token = ERC20Token(address(token));
_token.mint();
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
And along with this error i am recieving this error message
This contract may be abstract, not implement an abstract parent's methods completely or not invoke an inherited contract's constructor correctly.
what can i do to work around this?
You are trying to deploy an interface, which is not possible because it doesn't contain any code - just definition of functions.
If you already have a contract that implements this interface, you need to select it in the "Deploy" tab, see the screnshot:
If you haven't implemented the contract, you're in the very beginning and need to implement the whole thing to have a working ERC-20 token contract.
There is no "best way" to create an ERC-20 token, because each contract can be implemented differently but still implement the ERC-20 standard. For starters, I'd recommend reading the OpenZeppelin docs and their source codes to see how they implement the standard. Or if you google "minimal erc-20 contract", you'll find few more implementations that might be easier to grasp.
pragma solidity ^0.8;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
contract MyContract is IERC20 {
function totalSupply() external view returns (uint256) {
// TODO implement this function
}
function balanceOf(address who) external view returns (uint256) {
// TODO implement this function
}
// TODO implement all functions of the interface
}
I'm running this code on remix IDE. Everything is working fine except the function transfertocontracts(uint amount) public. I'm trying to transfer some ethers for e.g. 10 to my contract and then later using this function function Transfer_Contract_Amount() public I will transfer all the amount of contract to specific address.
The problem is that when I run function transfertocontracts(uint amount) public I'm getting this Error:
Note: The constructor should be payable if you send value. debug the transaction to get more information.
contract SLA {
address seller;
event DepositFunds(address from, uint amount);
constructor() payable public {
seller = msg.sender;
}
function transfertocontracts(uint amount) public {
address(this).transfer(amount);
}
function seePerson_Amount() public view returns(uint) {
return seller.balance;
}
function seeContract_Amount() public view returns(uint) {
return address(this).balance;
}
function Transfer_Contract_Amount() public {
seller.transfer(address(this).balance);
}
}
You can send ether only by using the value attribute which you can set while interacting with the Smart Contract. Below is the working code
pragma solidity >=0.4.22 <0.6.0;
contract SLA{
address payable seller;
event DepositFunds(address from, uint amount);
constructor() payable public {
seller = msg.sender;
}
function transfertocontracts(uint amount) payable public{
}
function seePerson_Amount() public view returns(uint){
return seller.balance;
}
function seeContract_Amount() public view returns(uint){
return address(this).balance;
}
function Transfer_Contract_Amount() payable public{
seller.transfer(address(this).balance);
}
}
To check you can run it on remix and on the run tab on the left side you can putt the value of ether to send and run the transfertocontracts function further to store the value its a good idea to use the msg.value.