Access to inherited variable in solidity to overwrite it - solidity

I want to override the following inherited function:
function _setBaseURI(string memory baseURI) public override(ERC721Full, ERC721Metadata) {
_baseURI = baseURI;
}
The problem is that it gives me the error Undeclared Identifier with _baseURI.
The variable was implemented private. Is it for that reason that it cannot be overwritten? And if so, why can the function be?
My contract:
pragma solidity ^0.6.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0-beta.0/contracts/token/ERC721/ERC721Full.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0-beta.0/contracts/drafts/Counters.sol";
contract GameItem is ERC721Full {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor() ERC721Full("GameItem", "ITM") public {
}
function awardItem(address player, string memory tokenURI) public returns (uint256) {
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(player, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
function _setBaseURI(string memory baseURI) public override(ERC721Full, ERC721Metadata) {
_baseURI = baseURI;
}
}
The Heritage
pragma solidity ^0.6.0;
import "../../GSN/Context.sol";
import "./ERC721.sol";
import "./IERC721Metadata.sol";
import "../../introspection/ERC165.sol";
contract ERC721Metadata is Context, ERC165, ERC721, IERC721Metadata {
// Token name
string private _name;
// Token symbol
string private _symbol;
// Base URI
string private _baseURI;
// Optional mapping for token URIs
mapping(uint256 => string) private _tokenURIs;
/*
* bytes4(keccak256('name()')) == 0x06fdde03
* bytes4(keccak256('symbol()')) == 0x95d89b41
* bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
*
* => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
*/
bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
/**
* #dev Constructor function
*/
constructor (string memory name, string memory symbol) public {
_name = name;
_symbol = symbol;
// register the supported interfaces to conform to ERC721 via ERC165
_registerInterface(_INTERFACE_ID_ERC721_METADATA);
}
/**
* #dev Gets the token name.
* #return string representing the token name
*/
function name() external view override returns (string memory) {
return _name;
}
/**
* #dev Gets the token symbol.
* #return string representing the token symbol
*/
function symbol() external view override returns (string memory) {
return _symbol;
}
/**
* #dev Returns the URI for a given token ID. May return an empty string.
*
* If the token's URI is non-empty and a base URI was set (via
* {_setBaseURI}), it will be added to the token ID's URI as a prefix.
*
* Reverts if the token ID does not exist.
*/
function tokenURI(uint256 tokenId) external view override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
// Even if there is a base URI, it is only appended to non-empty token-specific URIs
if (bytes(_tokenURI).length == 0) {
return "";
} else {
// abi.encodePacked is being used to concatenate strings
return string(abi.encodePacked(_baseURI, _tokenURI));
}
}
/**
* #dev Internal function to set the token URI for a given token.
*
* Reverts if the token ID does not exist.
*
* TIP: if all token IDs share a prefix (e.g. if your URIs look like
* `http://api.myproject.com/token/<id>`), use {_setBaseURI} to store
* it and save gas.
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
/**
* #dev Internal function to set the base URI for all token IDs. It is
* automatically added as a prefix to the value returned in {tokenURI}.
*
* _Available since v2.5.0._
*/
function _setBaseURI(string memory baseURI) internal virtual {
_baseURI = baseURI;
}
/**
* #dev Returns the base URI set via {_setBaseURI}. This will be
* automatically added as a preffix in {tokenURI} to each token's URI, when
* they are non-empty.
*
* _Available since v2.5.0._
*/
function baseURI() external view returns (string memory) {
return _baseURI;
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
if (to == address(0)) { // When burning tokens
// Clear metadata (if any)
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
}
}
}

It's a visibility issue.
If you want to access the _baseURI property in a derived contract, you need to make it at least internal (it's currently private).
Which also means copying a set of contracts locally so that you can update the ERC721Metadata.sol and import the updated version (and not the remote version) from the other contracts.
The _setBaseURI() function alone can be overridden because it's visible from your contract.
Private functions and state variables are only visible for the contract they are defined in and not in derived contracts.
Cannot access private property in a derived contract.
Source of the quote: https://docs.soliditylang.org/en/v0.8.3/contracts.html#visibility-and-getters

Related

Override `_authorizeUpgrade` when composing two upgradeable solidity contracts

I am missing something conceptually about override the _authorizeUpgrade function when composing two contracts. The setting is that I have two contracts, both upgradeable, as follows:
contract ERC721UpgradeableV1 is Initializable, ERC721Upgradeable, ERC721URIStorageUpgradeable, UUPSUpgradeable {
...
constructor() {
_disableInitializers();
}
function initializeERC721UpgradeableV1(string memory _name, string memory _symbol, string memory uri, address witness ) initializer public {
__ERC721_init(_name,_symbol);
__ERC721URIStorage_init();
__UUPSUpgradeable_init();
baseURI = uri;
admin721 = msg.sender;
witness721 = witness;
isPaused = true;
isWhitelistOnly = true;
}
function _authorizeUpgrade(address newImplementation) internal override {
require(msg.sender == admin721 || msg.sender == witness721);
}
....
}
contract PaymentSplitterUpgradeable is Context, ReentrancyGuard, Initializable, UUPSUpgradeable {
...
/**
* #dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at
* the matching position in the `shares` array.
*
* All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no
* duplicates in `payees`.
*/
function initializePaymentSplitter( address witness_, address[] memory payees, uint256[] memory shares_) payable public initializer {
require(payees.length == shares_.length, "PaymentSplitterUpgradeable: payees and shares length mismatch");
require(payees.length > 0, "PaymentSplitterUpgradeable: no payees");
paymentWitness = witness_;
paymentOwner = msg.sender;
_addPayoutWindow( payees, shares_);
}
function _authorizeUpgrade(address newImplementation) internal override {
require(msg.sender == paymentOwner || msg.sender == paymentWitness);
}
}
Now I am trying to write an upgradeable version of the two contracts via:
contract ERC721PaymentSplitterV1 is
Initializable,
UUPSUpgradeable,
ERC721UpgradeableV1,
PaymentSplitterUpgradeable
{
/**
* #dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE`, and `PAUSER_ROLE` to the account that
* deploys the contract.
*/
function initializeERC721LumoPaymentSplitter(
string memory _name,
string memory _symbol,
string memory uri,
address witness_,
address[] memory _payees,
uint256[] memory _shares
) initializer public {
initializeERC721UpgradeableV1(_name, _symbol, uri, witness_);
initializePaymentSplitter(witness_, _payees, _shares);
}
function _authorizeUpgrade(address newImplementation)
internal
override
{}
}
And receive a rather severe message about the function _authorizeUpgrade in ERC721PaymentSplitterV1 with:
`TypeError: Trying to override non-virtual function. Did you forget to add "virtual"?
--> contracts/project/ERC721UpgradeableV1.sol:38:5:
|
38 | function _authorizeUpgrade(address newImplementation) internal override {
| ^ (Relevant source part starts here and spans across multiple lines).
Note: Overriding function is here:
--> contracts/project/ERC721PaymentSplitter.sol:32:5:
|
32 | function _authorizeUpgrade(address newImplementation)
| ^ (Relevant source part starts here and spans across multiple lines).
TypeError: Trying to override non-`
ote: This contract:
--> #openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:22:1:
|
22 | abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
| ^ (Relevant source part starts here and spans across multiple lines).
Note: This contract:
--> contracts/project/ERC721Lumo.sol:10:1:
TypeError: Derived contract must override function "_msgData". Two or more base classes define function with same name and parameter types.
--> contracts/project/ERC721PaymentSplitter.sol:9:1:

DeclarationError: Identifier not found or not unique. --> project:/contracts/"".sol:26:23: | 26 | function initialize() initializer public

When running npx truffle compile, i get the above error message.
I am trying to transition an NFT smart contract into upgradeable form and have imported the relevant source codes. It deploys to testnet fine, but when replacing the constructor with "function Initialize() initializer pubic {" i get the above error message.
Can someone help?
I also get an "Identifier not found or not unique" by my "mapping(address=>bool) private _operatorEnabled;
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/security/Pausable.sol";
import "#openzeppelin/contracts/access/AccessControl.sol";
contract ERC721CarbonAsset is ERC721URIStorage, Pausable, AccessControl {
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
// Base URI
string private _baseUri;
address _forwarder;
mapping(uint256 => string) private _digests;
mapping(uint256 => string) private _infoRoots;
// Addresses under operator control
mapping(address => bool) private _operatorEnabled;
function initialize() initializer public {
// constructor() public ERC721("", "") Pausable() {
_baseUri = "";
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setupRole(PAUSER_ROLE, msg.sender);
_setupRole(MINTER_ROLE, msg.sender);
_setupRole(BURNER_ROLE, msg.sender);
_setupRole(OPERATOR_ROLE, msg.sender);
}
function pause() external onlyRole(PAUSER_ROLE) {
_pause();
}
function unpause() external onlyRole(PAUSER_ROLE) {
_unpause();
}
/**
* #dev See {ERC20-_beforeTokenTransfer}.
* Taken from ERC20Pausable
*
* Requirements:
*
* - the contract must not be paused.
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
super._beforeTokenTransfer(from, to, amount);
require(!paused(), "ERC721Pausable: token transfer while paused");
}
function mint(address to, uint256 tokenId, string memory tokenUri, string memory digest) public onlyRole(MINTER_ROLE) {
_mint(to, tokenId);
_setTokenURI(tokenId, tokenUri);
_digests[tokenId] = digest;
}
function burn(uint256 tokenId) public onlyRole(BURNER_ROLE) {
_burn(tokenId);
}
function setBaseURI(string memory uri) external onlyRole(OPERATOR_ROLE) {
_baseUri = uri;
}
/**
* #dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overriden in child contracts.
*/
function _baseURI() internal view virtual override returns (string memory) {
return _baseUri;
}
function infoRoot(uint256 tokenId) external view virtual returns (string memory) {
require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");
string memory _infoRoot = _infoRoots[tokenId];
// If there is no infoRoot set, return an empty string.
if (bytes(_infoRoot).length == 0) {
return "";
}
return _infoRoot;
}
function setInfoRoot(uint256 tokenId, string memory _infoRoot) external onlyRole(OPERATOR_ROLE) whenNotPaused() {
require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
_infoRoots[tokenId] = _infoRoot;
}
function digest(uint256 tokenId) external view virtual returns (string memory) {
require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");
string memory digest = _digests[tokenId];
// If there is no digest set, return an empty string.
if (bytes(digest).length == 0) {
return "";
}
return digest;
}
function setDigest(uint256 tokenId, string memory digest) external onlyRole(OPERATOR_ROLE) whenNotPaused() {
require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
_digests[tokenId] = digest;
}
// Operator initiatiated token transfer
function operatorTransfer(address recipient, uint256 tokenId) external onlyRole(OPERATOR_ROLE) whenNotPaused() returns (bool) {
address owner = ownerOf(tokenId);
require(isOperatorControlled(owner), "ERC721: sender not under operator control");
// Reset appoval
_approve(msg.sender, tokenId);
transferFrom(owner, recipient, tokenId);
return true;
}
// Address owner can enable their address for operator control
// Default state is operator disabled
function enableOperatorControl() external whenNotPaused() returns (bool) {
require(msgSender() != address(0), "ERC20: owner is a zero address");
require(!isOperatorControlled(msgSender()), "ERC20: owner already under operator control");
_operatorEnabled[msgSender()] = true;
return true;
}
// Operator role can remove operator control from an address
function disableOperatorControl(address owner) external onlyRole(OPERATOR_ROLE) whenNotPaused() returns (bool) {
require(owner != address(0), "ERC721: owner is a zero address");
require(isOperatorControlled(owner), "ERC721: owner not under operator control");
_operatorEnabled[owner] = false;
return true;
}
function isOperatorControlled(address owner) public view returns (bool) {
require(owner != address(0), "ERC721: owner is a zero address");
return _operatorEnabled[owner];
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, AccessControl) returns (bool) {
return super.supportsInterface(interfaceId);
}
function msgSender() internal view returns(address sender) {
if(msg.sender == _forwarder) {
bytes memory array = msg.data;
uint256 index = msg.data.length;
assembly {
// Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
sender := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)
}
} else {
sender = msg.sender;
}
return sender;
}
function setForwarder(address forwarder) external onlyRole(OPERATOR_ROLE) returns (bool) {
_forwarder = forwarder;
return true;
}
function getForwarder() external view returns (address) {
return _forwarder;
}
}
I tried to change the initializer function around a bit, inline with onlyInitializing functionality https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/releases/tag/v4.4.1
But that also returned a similar error regarding identifier not found or not unique
There were a few problems with the code:
there needs to be a constructor function that sets the token name and symbol (inherited from ERC721 contract)
the initialize function should not also have the word "initializer" in the function declaration
The code will work if with just the above, but there are warnings regarding the overlapping of your function named "digest" with the name "digest" of various input parameters and variables defined within a few functions. Easiest way to solve this is to change the function name
updated code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/security/Pausable.sol";
import "#openzeppelin/contracts/access/AccessControl.sol";
contract ERC721CarbonAsset is ERC721URIStorage, Pausable, AccessControl {
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
// Base URI
string private _baseUri;
address _forwarder;
mapping(uint256 => string) private _digests;
mapping(uint256 => string) private _infoRoots;
// Addresses under operator control
mapping(address => bool) private _operatorEnabled;
constructor() ERC721("BasicNFT", "BNFT") {}
function initialize() public {
// constructor() public ERC721("", "") Pausable() {
_baseUri = "";
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setupRole(PAUSER_ROLE, msg.sender);
_setupRole(MINTER_ROLE, msg.sender);
_setupRole(BURNER_ROLE, msg.sender);
_setupRole(OPERATOR_ROLE, msg.sender);
}
function pause() external onlyRole(PAUSER_ROLE) {
_pause();
}
function unpause() external onlyRole(PAUSER_ROLE) {
_unpause();
}
/**
* #dev See {ERC20-_beforeTokenTransfer}.
* Taken from ERC20Pausable
*
* Requirements:
*
* - the contract must not be paused.
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
super._beforeTokenTransfer(from, to, amount);
require(!paused(), "ERC721Pausable: token transfer while paused");
}
function mint(address to, uint256 tokenId, string memory tokenUri, string memory digest) public onlyRole(MINTER_ROLE) {
_mint(to, tokenId);
_setTokenURI(tokenId, tokenUri);
_digests[tokenId] = digest;
}
function burn(uint256 tokenId) public onlyRole(BURNER_ROLE) {
_burn(tokenId);
}
function setBaseURI(string memory uri) external onlyRole(OPERATOR_ROLE) {
_baseUri = uri;
}
/**
* #dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overriden in child contracts.
*/
function _baseURI() internal view virtual override returns (string memory) {
return _baseUri;
}
function infoRoot(uint256 tokenId) external view virtual returns (string memory) {
require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");
string memory _infoRoot = _infoRoots[tokenId];
// If there is no infoRoot set, return an empty string.
if (bytes(_infoRoot).length == 0) {
return "";
}
return _infoRoot;
}
function setInfoRoot(uint256 tokenId, string memory _infoRoot) external onlyRole(OPERATOR_ROLE) whenNotPaused() {
require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
_infoRoots[tokenId] = _infoRoot;
}
function digestDifferentName(uint256 tokenId) external view virtual returns (string memory) {
require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");
string memory digest = _digests[tokenId];
// If there is no digest set, return an empty string.
if (bytes(digest).length == 0) {
return "";
}
return digest;
}
function setDigest(uint256 tokenId, string memory digest) external onlyRole(OPERATOR_ROLE) whenNotPaused() {
require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
_digests[tokenId] = digest;
}
// Operator initiatiated token transfer
function operatorTransfer(address recipient, uint256 tokenId) external onlyRole(OPERATOR_ROLE) whenNotPaused() returns (bool) {
address owner = ownerOf(tokenId);
require(isOperatorControlled(owner), "ERC721: sender not under operator control");
// Reset appoval
_approve(msg.sender, tokenId);
transferFrom(owner, recipient, tokenId);
return true;
}
// Address owner can enable their address for operator control
// Default state is operator disabled
function enableOperatorControl() external whenNotPaused() returns (bool) {
require(msgSender() != address(0), "ERC20: owner is a zero address");
require(!isOperatorControlled(msgSender()), "ERC20: owner already under operator control");
_operatorEnabled[msgSender()] = true;
return true;
}
// Operator role can remove operator control from an address
function disableOperatorControl(address owner) external onlyRole(OPERATOR_ROLE) whenNotPaused() returns (bool) {
require(owner != address(0), "ERC721: owner is a zero address");
require(isOperatorControlled(owner), "ERC721: owner not under operator control");
_operatorEnabled[owner] = false;
return true;
}
function isOperatorControlled(address owner) public view returns (bool) {
require(owner != address(0), "ERC721: owner is a zero address");
return _operatorEnabled[owner];
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, AccessControl) returns (bool) {
return super.supportsInterface(interfaceId);
}
function msgSender() internal view returns(address sender) {
if(msg.sender == _forwarder) {
bytes memory array = msg.data;
uint256 index = msg.data.length;
assembly {
// Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
sender := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)
}
} else {
sender = msg.sender;
}
return sender;
}
function setForwarder(address forwarder) external onlyRole(OPERATOR_ROLE) returns (bool) {
_forwarder = forwarder;
return true;
}
function getForwarder() external view returns (address) {
return _forwarder;
}
}
As a general rule of thumb, upgradeable contracts cannot contain Constructors.
See https://docs.openzeppelin.com/learn/upgrading-smart-contracts
I have added "#openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
and inherited from this in the contract declaration, which now doesn't return the initial error message.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "#openzeppelin/contracts/security/Pausable.sol";
import "#openzeppelin/contracts/access/AccessControl.sol";
import "#openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
abstract contract ERC721CarbonAsset is ERC721URIStorage, Pausable, AccessControl, Initializable {
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
// Base URI
string private _baseUri;
address _forwarder;
mapping(uint256 => string) private _digests;
mapping(uint256 => string) private _infoRoots;
// Addresses under operator control
mapping(address => bool) private _operatorEnabled;
function initialize() initializer public {
// constructor() public ERC721("", "") Pausable() {
_baseUri = "";
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setupRole(PAUSER_ROLE, msg.sender);
_setupRole(MINTER_ROLE, msg.sender);
_setupRole(BURNER_ROLE, msg.sender);
_setupRole(OPERATOR_ROLE, msg.sender);
}
function pause() external onlyRole(PAUSER_ROLE) {
_pause();
}
function unpause() external onlyRole(PAUSER_ROLE) {
_unpause();
}
/**
* #dev See {ERC20-_beforeTokenTransfer}.
* Taken from ERC20Pausable
*
* Requirements:
*
* - the contract must not be paused.
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
super._beforeTokenTransfer(from, to, amount);
require(!paused(), "ERC721Pausable: token transfer while paused");
}
function mint(address to, uint256 tokenId, string memory tokenUri, string memory digest) public onlyRole(MINTER_ROLE) {
_mint(to, tokenId);
_setTokenURI(tokenId, tokenUri);
_digests[tokenId] = digest;
}
function burn(uint256 tokenId) public onlyRole(BURNER_ROLE) {
_burn(tokenId);
}
function setBaseURI(string memory uri) external onlyRole(OPERATOR_ROLE) {
_baseUri = uri;
}
/**
* #dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overriden in child contracts.
*/
function _baseURI() internal view virtual override returns (string memory) {
return _baseUri;
}
function infoRoot(uint256 tokenId) external view virtual returns (string memory) {
require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");
string memory _infoRoot = _infoRoots[tokenId];
// If there is no infoRoot set, return an empty string.
if (bytes(_infoRoot).length == 0) {
return "";
}
return _infoRoot;
}
function setInfoRoot(uint256 tokenId, string memory _infoRoot) external onlyRole(OPERATOR_ROLE) whenNotPaused() {
require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
_infoRoots[tokenId] = _infoRoot;
}
function digest(uint256 tokenId) external view virtual returns (string memory) {
require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");
string memory digest = _digests[tokenId];
// If there is no digest set, return an empty string.
if (bytes(digest).length == 0) {
return "";
}
return digest;
}
function setDigest(uint256 tokenId, string memory digest) external onlyRole(OPERATOR_ROLE) whenNotPaused() {
require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
_digests[tokenId] = digest;
}
// Operator initiatiated token transfer
function operatorTransfer(address recipient, uint256 tokenId) external onlyRole(OPERATOR_ROLE) whenNotPaused() returns (bool) {
address owner = ownerOf(tokenId);
require(isOperatorControlled(owner), "ERC721: sender not under operator control");
// Reset appoval
_approve(msg.sender, tokenId);
transferFrom(owner, recipient, tokenId);
return true;
}
// Address owner can enable their address for operator control
// Default state is operator disabled
function enableOperatorControl() external whenNotPaused() returns (bool) {
require(msgSender() != address(0), "ERC20: owner is a zero address");
require(!isOperatorControlled(msgSender()), "ERC20: owner already under operator control");
_operatorEnabled[msgSender()] = true;
return true;
}
// Operator role can remove operator control from an address
function disableOperatorControl(address owner) external onlyRole(OPERATOR_ROLE) whenNotPaused() returns (bool) {
require(owner != address(0), "ERC721: owner is a zero address");
require(isOperatorControlled(owner), "ERC721: owner not under operator control");
_operatorEnabled[owner] = false;
return true;
}
function isOperatorControlled(address owner) public view returns (bool) {
require(owner != address(0), "ERC721: owner is a zero address");
return _operatorEnabled[owner];
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, AccessControl) returns (bool) {
return super.supportsInterface(interfaceId);
}
function msgSender() internal view returns(address sender) {
if(msg.sender == _forwarder) {
bytes memory array = msg.data;
uint256 index = msg.data.length;
assembly {
// Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
sender := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)
}
} else {
sender = msg.sender;
}
return sender;
}
function setForwarder(address forwarder) external onlyRole(OPERATOR_ROLE) returns (bool) {
_forwarder = forwarder;
return true;
}
function getForwarder() external view returns (address) {
return _forwarder;
}
}

contracts/3_Ballot.sol:33:37: TypeError: Named argument does not match function declaration

from solidity:
contracts/3_Ballot.sol:33:37: TypeError: Named argument does not match function declaration.
Request memory newRequest = Request({
^ (Relevant source part starts here and spans across multiple lines).
I get this error every time. What should i do for the solve it?
pragma solidity ^0.4.17;
contract Campaign {
struct Request {
string description;
uint value;
address recipient;
bool complete;
}
Request[] public requests;
address public manager;
uint public minimumContirbution;
address[] public approvers;
modifier restricted() {
require (msg.sender == manager);
_;
}
function Campaign (uint minimum) public {
manager = msg.sender;
minimumContirbution = minimum;
}
function contribute () public payable {
require(msg.value > minimumContirbution);
approvers.push(msg.sender);
}
function createRequest(string description, uint value, address recipient) restricted public {
Request memory newRequest = Request({
description: description,
value: value,
restricted: restricted,
complete: false
});
requests.push(newRequest);
}
}
You can define the Request struct in this way and push it into requests array:
function createRequest(string description, uint value, address recipient) restricted public {
Request memory newRequest = Request(description, value, recipient, false);
requests.push(newRequest);
}
In this way, you can add the struct into your array and can retrieve with all parameters setted previously.
Because you're are using wrong argument(restricted) inside you Request type
try this:
Request memory newRequest = Request({
descritption: descritpion,
value: value,
recipient: recipient,
complete: false
});

Type is not callable _isExcludedFromFee[(owner)] = true;

My token contract with solidity 0.8.4 is catching:
TypeError: Type is not callable
_isExcludedFromFee[(owner)] = true;
^^^^^^^^
From:
constructor () {
_rOwned[_msgSender()] = _rTotal;
IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F);
// Create a uniswap pair for this new token
uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
.createPair(address(this), _uniswapV2Router.WETH());
// set the rest of the contract variables
uniswapV2Router = _uniswapV2Router;
_isExcludedFromFee[owner()] = true;
_isExcludedFromFee[address(this)] = true;
emit Transfer(address(0), _msgSender(), _tTotal);
initialize();
pause();
}
I believe it is "owner" that is causing the error, and will attach the Ownable and token contract below. There is an owner function that is typically included SafeMoon's Ownable that returns _owner but that just breaks everything more since I have newly declared address public owner.
Was able to correct by making these changes:
contract Ownable is Context {
// OWNER DATA
address public _owner;
address public _proposedOwner;
address private _oldOwner;
uint256 private _lockTime;
// OWNABLE EVENTS
event OwnershipTransferProposed(
address indexed currentOwner,
address indexed proposedOwner
);
event OwnershipTransferDisregarded(
address indexed oldProposedOwner
);
event OwnershipTransferred(
address indexed oldOwner,
address indexed newOwner
);
/**
* #dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* #dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* #dev Returns the address of the current owner.
*/
/**
* #dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* #dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* #dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
function getUnlockTime() public view returns (uint256) {
return _lockTime;
}
//Locks the contract for owner for the amount of time provided
function lock(uint256 time) public virtual onlyOwner {
_oldOwner = _owner;
_owner = address(0);
_lockTime = block.timestamp + time;
emit OwnershipTransferred(_owner, address(0));
}
//Unlocks the contract for owner when _lockTime is exceeds
function unlock() public virtual {
require(_oldOwner == msg.sender, "You don't have permission to unlock");
require(block.timestamp > _lockTime , "Contract is locked until 7 days");
emit OwnershipTransferred(_owner, _oldOwner);
_owner = _oldOwner;
}
}

Factory error The called function should be payable

I am using the Opensea Creatures repository (https://github.com/ProjectOpenSea/opensea-creatures.git) to make a Factory and create my ERC721 tokens. I have added the function _setTokenURI (newTokenId, metadataURI); in ERC721Tradable.sol to add the URI when doing mint but it gives me the following error:
The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance.
Debug the transaction to get more information.
the files involved are these:
CreatureFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/access/Ownable.sol";
import "openzeppelin-solidity/contracts/utils/Strings.sol";
import "openzeppelin-solidity/contracts/token/ERC721/ERC721.sol";
import "./IFactoryERC721.sol";
import "./Creature.sol";
contract CreatureFactory is FactoryERC721, Ownable {
using Strings for string;
event Transfer(
address indexed from,
address indexed to,
uint256 indexed tokenId
);
address public proxyRegistryAddress;
address public nftAddress;
address public lootBoxNftAddress;
string public baseURI = "https://terrorverso.herokuapp.com/api/token/";
/*
* Enforce the existence of only 100 OpenSea creatures.
*/
uint256 CREATURE_SUPPLY = 100;
/*
* Three different options for minting Creatures (basic, premium, and gold).
*/
uint256 NUM_OPTIONS = 3;
uint256 SINGLE_CREATURE_OPTION = 0;
uint256 MULTIPLE_CREATURE_OPTION = 1;
uint256 LOOTBOX_OPTION = 2;
uint256 NUM_CREATURES_IN_MULTIPLE_CREATURE_OPTION = 4;
constructor(address _proxyRegistryAddress, address _nftAddress) {
proxyRegistryAddress = _proxyRegistryAddress;
nftAddress = _nftAddress;
fireTransferEvents(address(0), owner());
}
function name() override external pure returns (string memory) {
return "Factory";
}
function symbol() override external pure returns (string memory) {
return "FACT";
}
function supportsFactoryInterface() override public pure returns (bool) {
return true;
}
function numOptions() override public view returns (uint256) {
return NUM_OPTIONS;
}
function transferOwnership(address newOwner) override public onlyOwner {
address _prevOwner = owner();
super.transferOwnership(newOwner);
fireTransferEvents(_prevOwner, newOwner);
}
function fireTransferEvents(address _from, address _to) private {
for (uint256 i = 0; i < NUM_OPTIONS; i++) {
emit Transfer(_from, _to, i);
}
}
function mint(uint256 _optionId, address _toAddress, string memory metadataURI) override public {
// Must be sent from the owner proxy or owner.
ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
assert( address(proxyRegistry.proxies(owner())) == _msgSender() || owner() == _msgSender() || _msgSender() == lootBoxNftAddress );
require(canMint(_optionId));
Creature openSeaCreature = Creature(nftAddress);
if (_optionId == SINGLE_CREATURE_OPTION) {
openSeaCreature.mintTo(_toAddress,metadataURI);
} else if (_optionId == MULTIPLE_CREATURE_OPTION) {
for (
uint256 i = 0;
i < NUM_CREATURES_IN_MULTIPLE_CREATURE_OPTION;
i++
) {
openSeaCreature.mintTo(_toAddress,metadataURI);
}
}
}
function canMint(uint256 _optionId) override public view returns (bool) {
if (_optionId >= NUM_OPTIONS) {
return false;
}
Creature openSeaCreature = Creature(nftAddress);
uint256 creatureSupply = openSeaCreature.totalSupply();
uint256 numItemsAllocated = 0;
if (_optionId == SINGLE_CREATURE_OPTION) {
numItemsAllocated = 1;
} else if (_optionId == MULTIPLE_CREATURE_OPTION) {
numItemsAllocated = NUM_CREATURES_IN_MULTIPLE_CREATURE_OPTION;
}
return creatureSupply < (CREATURE_SUPPLY - numItemsAllocated);
}
function tokenURI(uint256 _optionId) override external view returns (string memory) {
return string(abi.encodePacked(baseURI, Strings.toString(_optionId)));
}
/**
* Hack to get things to work automatically on OpenSea.
* Use transferFrom so the frontend doesn't have to worry about different method names.
*/
function transferFrom(
address _from,
address _to,
uint256 _tokenId,
string memory metadataURI
) public {
mint(_tokenId, _to, metadataURI);
}
/**
* Hack to get things to work automatically on OpenSea.
* Use isApprovedForAll so the frontend doesn't have to worry about different method names.
*/
function isApprovedForAll(address _owner, address _operator)
public
view
returns (bool)
{
if (owner() == _owner && _owner == _operator) {
return true;
}
ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
if (
owner() == _owner &&
address(proxyRegistry.proxies(_owner)) == _operator
) {
return true;
}
return false;
}
/**
* Hack to get things to work automatically on OpenSea.
* Use isApprovedForAll so the frontend doesn't have to worry about different method names.
*/
function ownerOf(uint256 _tokenId) public view returns (address _owner) {
return owner();
}
}
ERC721Tradable.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC721/ERC721.sol";
import "openzeppelin-solidity/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "openzeppelin-solidity/contracts/access/Ownable.sol";
import "openzeppelin-solidity/contracts/utils/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/utils/Strings.sol";
import "openzeppelin-solidity/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "./common/meta-transactions/ContentMixin.sol";
import "./common/meta-transactions/NativeMetaTransaction.sol";
contract OwnableDelegateProxy {}
contract ProxyRegistry {
mapping(address => OwnableDelegateProxy) public proxies;
}
/**
* #title ERC721Tradable
* ERC721Tradable - ERC721 contract that whitelists a trading address, and has minting functionality.
*/
abstract contract ERC721Tradable is ContextMixin, ERC721Enumerable, NativeMetaTransaction, Ownable, ERC721URIStorage {
using SafeMath for uint256;
address proxyRegistryAddress;
uint256 private _currentTokenId = 0;
constructor(
string memory _name,
string memory _symbol,
address _proxyRegistryAddress
) ERC721(_name, _symbol) {
proxyRegistryAddress = _proxyRegistryAddress;
_initializeEIP712(_name);
}
/**
* #dev Mints a token to an address with a tokenURI.
* #param _to address of the future owner of the token
*/
function mintTo(address _to, string memory metadataURI) public onlyOwner {
uint256 newTokenId = _getNextTokenId();
_mint(_to, newTokenId);
_setTokenURI(newTokenId, metadataURI);
_incrementTokenId();
}
/**
* #dev calculates the next token ID based on value of _currentTokenId
* #return uint256 for the next token ID
*/
function _getNextTokenId() private view returns (uint256) {
return _currentTokenId.add(1);
}
/**
* #dev increments the value of _currentTokenId
*/
function _incrementTokenId() private {
_currentTokenId++;
}
function baseTokenURI() virtual public pure returns (string memory);
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 _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);
}
/**
* Override isApprovedForAll to whitelist user's OpenSea proxy accounts to enable gas-less listings.
*/
function isApprovedForAll(address owner, address operator)
override
public
view
returns (bool)
{
// Whitelist OpenSea proxy contract for easy trading.
ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
if (address(proxyRegistry.proxies(owner)) == operator) {
return true;
}
return super.isApprovedForAll(owner, operator);
}
/**
* This is used instead of msg.sender as transactions won't be sent by the original token owner, but by OpenSea.
*/
function _msgSender()
internal
override
view
returns (address sender)
{
return ContextMixin.msgSender();
}
}
and Creature.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./ERC721Tradable.sol";
/**
* #title Creature
* Creature - a contract for my non-fungible creatures.
*/
contract Creature is ERC721Tradable{
constructor(address _proxyRegistryAddress)
ERC721Tradable("ExampleNFT", "EXA", _proxyRegistryAddress)
{}
function baseTokenURI() override public pure returns (string memory) {
return "https://example.com/api/token/";
}
function contractURI() public pure returns (string memory) {
return "https://creatures-api.opensea.io/contract/opensea-creatures";
}
}