Gm, this is my first question here but the forum has been immensely helpful to me so far
I'm trying to quickly spin up an implementation of ERC721 with the ERC721Votes extension from v4.5.0 (I wish to use this to build a NFT-based Governor):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/draft-ERC721Votes.sol";
contract NFTName is ERC721("NFTName", "NFTSYMBOL"), ERC721Votes {
}
I get the following compiler message: Derived contract must override function "_afterTokenTransfer". Two or more base classes define function with same name and parameter types. After following the message's advice and modifying the code to override _afterTokenTransfer:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/draft-ERC721Votes.sol";
contract NFTName is ERC721("NFTName", "NFTSYMBOL"), ERC721Votes {
// added
function _afterTokenTransfer(
address from,
address to,
uint256 tokenId
) internal override(ERC721, ERC721Votes) {
super._afterTokenTransfer(from, to, tokenId);
}
}
I get the following message, which I don't know how to resolve:
Contract "NFTName" should be marked as abstract.
Would appreciate some feedback on how to get this compiling. Using hardhat v2.8.4 on Node v16.6.1.
For setting up ERC721Votes you can get some help from Contracts Wizard:
For setting up the Governor you can also use Contracts Wizard, and the resulting contract receives the address of the voting token in the constructor. Our guide How to set up on-chain governance will probably also be helpful.
As far as I know, you don't NEED a TimeLock to make Governance work (But there is an option to add that and is used quite often).
As for how does the Governor know about the ERC721... the constructor of the Governor contract will have an IVotes _token parameter. You can go to the Governor tab on the Wizard and click on ERC20Votes radio button (they should rename this to just "Votes"), if you look at the code, you'll see the constructor parameter there. As long as your ERC721 is a ERC721Votes, then it will also implement IVotes, so once you pass it as a parameter, it will be "aware" that it exists and what its location is.
Error is identified. I just don't know how to fix. I know you're busy, but would really appreciate your help. Perhaps you can share a solution?
MyGovernor.sol from the Wizard: Any idea of what additions to MyGovernor.sol would be needed for it to work with my ERC721Votes token mentioned in 1 above?? I'm thinking I need to add this:
If none of the above, how is it "connected and aware" of my ERC721Votes token?
Timelock: I thought I needed a separate TimeLock.sol file. Apparently I don't. So I can interact directly with TimelockController.sol by means of MyGovernor.sol mentioned it point 2 above, right?.
I will re-read the Governance doc you mentioned. Maybe I overlooked something during my first read of it!
When you generate your Governor using Wizard, there is a "_token" constructor argument. When you deploy the governor you have to pass in the address of your ERC721Votes contract that you deployed previously.
So, if I understand everything correctly, after deploying my ERC721VotesMinter.sol and the TimelockController.sol template, I just manually update MyGovernor.sol with the following: