ERC721VotesLib
Title: ERC721VotesLib
Authors: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80), Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/extensions/ERC721Votes.sol)
Library adding ERC-5805 voting power to ERC-721, where each token is one voting unit.
No own storage, init or ERC-165 id: it moves voting units in VotesLib (which registers IVotes) as
ERC721Lib moves tokens. The base ERC721Lib has no hook (D25, option (a)), so voting power stays correct
only while every token movement goes through _update here. The ERC721Votes facet replaces the base
transfer selectors to do that. Any other code that moves a token on a votes diamond (a mint, a burn, or an
authorization-free transfer) must call this library's _mint, _safeMint, _burn, _transfer,
_safeTransfer or _update, never ERC721Lib's. ERC721Burnable and ERC721Wrapper call ERC721Lib
directly, so they are mutually exclusive with this extension. The CCTPHookReceipt example also mints through
ERC721Lib._mint; it is a standalone contract that cannot take this facet, and a fork of it that adds
votes must mint here.
Differences from OpenZeppelin v5.6.1:
- OpenZeppelin overrides
_update, so every internal path (_mint,_burn,_transfer,_safeTransfer) moves voting units automatically. Here only this library's wrappers do:ERC721Lib._transferand the other ERC721Lib internals move no units. - OpenZeppelin overrides
_increaseBalanceto move batch-minted units. This library cannot see a batch (ERC721ConsecutiveLib._mintConsecutive), so the pair is forbidden: a batch on a votes diamond and ERC721VotesInit on a batch-minting diamond both revertERC721VotesForbiddenBatchMint. - Voting units are read from the ERC-721 balance by delegate and delegateBySig, which replace the base
Votes facet's ERC-20-balance versions; OpenZeppelin overrides
_getVotingUnitsinstead.
Functions
transferFrom
ERC721Lib.transferFrom that also moves one voting unit.
function transferFrom(address from, address to, uint256 tokenId) internal;Parameters
| Name | Type | Description |
|---|---|---|
| from | address | |
| to | address | |
| tokenId | uint256 |
safeTransferFrom
ERC721Lib.safeTransferFrom that also moves one voting unit.
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) internal;Parameters
| Name | Type | Description |
|---|---|---|
| from | address | |
| to | address | |
| tokenId | uint256 | |
| data | bytes |
_mint
ERC721Lib._mint that also mints one voting unit.
function _mint(address to, uint256 tokenId) internal;Parameters
| Name | Type | Description |
|---|---|---|
| to | address | |
| tokenId | uint256 |
_safeMint
ERC721Lib._safeMint that also mints one voting unit.
function _safeMint(address to, uint256 tokenId, bytes memory data) internal;Parameters
| Name | Type | Description |
|---|---|---|
| to | address | |
| tokenId | uint256 | |
| data | bytes |
_burn
ERC721Lib._burn that also burns one voting unit.
function _burn(uint256 tokenId) internal;Parameters
| Name | Type | Description |
|---|---|---|
| tokenId | uint256 |
_transfer
ERC721Lib._transfer that also moves one voting unit: moves tokenId without an authorization check, for
permissioned or signature-based transfer paths.
function _transfer(address from, address to, uint256 tokenId) internal;Parameters
| Name | Type | Description |
|---|---|---|
| from | address | |
| to | address | |
| tokenId | uint256 |
_safeTransfer
ERC721Lib._safeTransfer that also moves one voting unit. The receiver sees msg.sender as operator.
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal;Parameters
| Name | Type | Description |
|---|---|---|
| from | address | |
| to | address | |
| tokenId | uint256 | |
| data | bytes |
_update
ERC721Lib._update followed by OpenZeppelin's _transferVotingUnits(previousOwner, to, 1).
Like OpenZeppelin, it moves the unit before the caller checks the previous owner; every caller here reverts on a bad previous owner, which undoes the move.
function _update(address to, uint256 tokenId, address auth) internal returns (address previousOwner);Parameters
| Name | Type | Description |
|---|---|---|
| to | address | |
| tokenId | uint256 | |
| auth | address |
Returns
| Name | Type | Description |
|---|---|---|
| previousOwner | address |
delegate
Delegates the caller's votes to delegatee, using the caller's ERC-721 balance as voting units.
function delegate(address delegatee) internal;Parameters
| Name | Type | Description |
|---|---|---|
| delegatee | address |
delegateBySig
Delegates by EIP-712 signature, using the signer's ERC-721 balance as voting units.
Recovers the signer first to read its balance, then consumes the nonce and delegates, as
ERC20VotesLib.delegateBySig does. Keep the nonce handling in step with VotesLib.delegateBySig.
function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) internal;Parameters
| Name | Type | Description |
|---|---|---|
| delegatee | address | |
| nonce | uint256 | |
| expiry | uint256 | |
| v | uint8 | |
| r | bytes32 | |
| s | bytes32 |
_getVotingUnits
The voting units of account: its ERC-721 balance.
function _getVotingUnits(address account) internal view returns (uint256);Parameters
| Name | Type | Description |
|---|---|---|
| account | address |
Returns
| Name | Type | Description |
|---|---|---|
| <none> | uint256 |