contract NFTVotesToken is ERC721, ERC721Votes { uint256 tokenCount; mapping(uint256 => uint256) tokenIdToVotingPower; function initialize() public payable initializer { __ERC721_init("NFT Votes Token", "NVT"); } function _afterTokenTransfer( address from, address to, uint256 tokenId ) internal override(ERC721, ERC721Votes) { _transferVotingUnits(from, to, LibVotesPower.votesStorage().tokenIdToVotingPower[tokenId]); super._afterTokenTransfer(from, to, tokenId); } function mint(address to, uint256 tokenPower) public { require(to != address(0), "ERC721: mint to the zero address"); require(tokenPower != 0, "ERC721: power must be > 0"); tokenCount++; uint256 tokenId = tokenCount; _beforeTokenTransfer(address(0), to, tokenId); tokenIdToVotingPower[tokenId] = tokenPower; _balances[to] += tokenPower; _owners[tokenId] = to; _mint(to, tokenId); } function _mint(address to, uint256 tokenId) internal override(ERC721) { emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId); } function transfer( address from, address to, uint256 tokenId ) public { _transfer(from, to, tokenId); } function _transfer( address from, address to, uint256 tokenId ) internal override(ERC721) { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); uint256 tokenPower = tokenIdToVotingPower[tokenId]; _balances[from] -= tokenPower; _balances[to] += tokenPower; _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId); } function burn(uint256 tokenId) public { _burn(tokenId); } function _burn(uint256 tokenId) internal override(ERC721) { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); ERC721Storage.layout()._balances[owner] -= tokenIdToVotingPower[tokenId]; delete tokenIdToVotingPower[tokenId]; delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId); } }