Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-Fungible Votes - assign NFTs with different voting weight #3755

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2e97db0
Copy of Votes.sol
toledoroy Oct 7, 2022
5745054
Copy ERC721Votes
toledoroy Oct 7, 2022
551328b
Copy Votes.behaviour.js
toledoroy Oct 7, 2022
4230cf9
Updated to match expected behaviour without opt-out option
toledoroy Oct 7, 2022
65e872c
Copied ERC721Votes.test.js
toledoroy Oct 7, 2022
e0445a1
Updated tests for no opt-out behavior
toledoroy Oct 7, 2022
ef50c5a
Copy ERC721VotesMock
toledoroy Oct 7, 2022
70cffe5
Renamed token power function
toledoroy Oct 7, 2022
e22ca55
Modified Votes contract to always maintain a current copy of user's v…
toledoroy Oct 7, 2022
513c4de
Made invalid/irrelevant signature revert with 'Votes: no units to tra…
toledoroy Oct 7, 2022
0397452
[REFAC] pull token power directly from the contract
toledoroy Oct 7, 2022
f5ea083
[FIX] Should not be able to delegate to address(0)
toledoroy Oct 7, 2022
198db0f
Adjustments for forced votes - varying power for each token
toledoroy Oct 7, 2022
7f17306
Mock contract for ERC721VotesForced
toledoroy Oct 7, 2022
2c6e3e6
Added test: 'can`t delegate to zero-address'
toledoroy Oct 7, 2022
6fc4037
Merge branch 'OpenZeppelin:master' into master
toledoroy Oct 7, 2022
3aed8b4
Removed the 'drafts' from draft-ERC721VotesForced
toledoroy Oct 7, 2022
40a7a62
Lint
toledoroy Oct 8, 2022
4754b7f
Linting
toledoroy Oct 8, 2022
b84a325
Renamed VotesForced to VotesNF (for Non-Fungible Votes)
toledoroy Oct 9, 2022
ed8fc76
Removed the Forced-Opt-In mechanism and instead using Votes as is.
toledoroy Oct 9, 2022
30cea57
Prettier
toledoroy Oct 9, 2022
73e5d37
Cleanup
toledoroy Oct 9, 2022
8b996d8
Typo
toledoroy Oct 9, 2022
8bd0de4
Typo
toledoroy Oct 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions contracts/mocks/ERC721VotesNFMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.4;

import "../token/ERC721/extensions/ERC721VotesNF.sol";

contract ERC721VotesNFMock is ERC721VotesNF {
constructor(string memory name, string memory symbol) ERC721(name, symbol) EIP712(name, "1") {}

/**
* @dev Calculate the voting power of each token
* token weight expected to remain consistent and immutable.
*/
function powerOfToken(uint256 tokenId) public pure override returns (uint256) {
if (tokenId <= 1000) return tokenId * 2;
return tokenId / 2;
}

function getTotalSupply() public view returns (uint256) {
return _getTotalSupply();
}

function mint(address account, uint256 tokenId) public {
_mint(account, tokenId);
}

function burn(uint256 tokenId) public {
_burn(tokenId);
}

function getChainId() external view returns (uint256) {
return block.chainid;
}
}
87 changes: 87 additions & 0 deletions contracts/token/ERC721/extensions/ERC721VotesNF.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/extensions/draft-ERC721Votes.sol)

pragma solidity ^0.8.4;

import "../ERC721.sol";
import "../../../governance/utils/Votes.sol";

/**
* @dev Extension of ERC721 to support voting and delegation as implemented by {VotesForces}, where every NFT may
* have different voting power.
*
* All tokens count as votes, even if not delegated. There's no need to delegate to oneself.
* There's an additional cost for every token transfer (more gas).
* Token holders may cast their vote themselves or delegate their vote to a representative.
*
*/
abstract contract ERC721VotesNF is ERC721, Votes {
// Track the current undelegated balance for each account.
// this allows to support different voting power for different tokens
mapping(address => uint256) private _unitsBalance;

/**
* @dev Calculate the voting power of each token
* token weight expected to remain consistent and immutable.
*/
function powerOfToken(uint256) public pure virtual returns (uint256) {
return 1;
}

/**
* @dev Must return the voting units held by an account.
*/
function _getVotingUnits(address account) internal view override returns (uint256) {
return _unitsBalance[account];
}

/**
* @dev Track all power-adjusted balances
*/
function _transferVotingUnits(
address from,
address to,
uint256 amount
) internal virtual override {
if (from != address(0)) {
//Units Removed
_unitsBalance[from] = _unitsBalance[from] - amount;
}
if (to != address(0)) {
//Units Added
_unitsBalance[to] = _unitsBalance[to] + amount;
}
super._transferVotingUnits(from, to, amount);
}

/**
* @dev Adjusts votes when tokens are transferred.
*
* Emits a {IVotes-DelegateVotesChanged} event.
*/
function _afterTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
_transferVotingUnits(from, to, powerOfToken(tokenId));
super._afterTokenTransfer(from, to, tokenId);
}

/**
* @dev Adjusts votes when a batch of tokens is transferred.
*
* Emits a {IVotes-DelegateVotesChanged} event.
*/
function _afterConsecutiveTokenTransfer(
address from,
address to,
uint256 first,
uint96 size
) internal virtual override {
for (uint256 i = 0; i < size; ++i) {
_transferVotingUnits(from, to, powerOfToken(first + i));
}
super._afterConsecutiveTokenTransfer(from, to, first, size);
}
}
Loading