Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions contracts/interfaces/IGovernor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ interface IGovernor {
function propose(Transaction[] calldata transactions, string calldata description) external returns (uint proposalId);
function execute(uint proposalId) external payable;

function getVoteWeight(address voter) external view returns (uint);

function getProposal(uint proposalId) external view returns (Proposal memory);
function getProposalDescription(uint proposalId) external view returns (string memory);
function getProposalTransactions(uint proposalId) external view returns (Transaction[] memory);
Expand Down
14 changes: 14 additions & 0 deletions contracts/interfaces/IVotePower.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity ^0.8.28;

interface IVotePower {

function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);

function balanceOf(address member) external view returns (uint);
function totalSupply() external view returns (uint);

}
4 changes: 4 additions & 0 deletions contracts/modules/governance/Governor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ contract Governor is IGovernor, RegistryAware, Multicall {
tokenController = ITokenController(fetch(C_TOKEN_CONTROLLER));
}

function getVoteWeight(address voter) public view returns (uint) {
return registry.isMember(voter) ? _getVoteWeight(voter) : 0;
}

function _getVoteWeight(address voter) internal view returns (uint) {
uint totalSupply = tokenController.totalSupply();
uint weight = tokenController.totalBalanceOf(voter) + 1 ether;
Expand Down
65 changes: 15 additions & 50 deletions contracts/modules/governance/VotePower.sol
Original file line number Diff line number Diff line change
@@ -1,68 +1,33 @@
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity ^0.8.18;
pragma solidity ^0.8.28;

import "../../interfaces/IGovernance.sol";
import "../../interfaces/IMemberRoles.sol";
import "../../interfaces/INXMMaster.sol";
import "../../abstract/RegistryAware.sol";
import "../../interfaces/IGovernor.sol";
import "../../interfaces/INXMToken.sol";
import "../../interfaces/ITokenController.sol";
import "../../interfaces/IVotePower.sol";

contract VotePower {
/// @notice ERC20-like contract to be used in Snapshot voting
contract VotePower is IVotePower, RegistryAware {

string constant public name = "NXM balance with delegations";
string constant public symbol = "NXMD";
uint8 constant public decimals = 18;

INXMMaster immutable public master;
IGovernor public immutable governor;
INXMToken public immutable token;

enum Role {Unassigned, AdvisoryBoard, Member}

constructor(INXMMaster _master) {
master = _master;
}

function totalSupply() public view returns (uint) {
return INXMToken(master.tokenAddress()).totalSupply();
constructor(address _registry) RegistryAware(_registry) {
governor = IGovernor(registry.getContractAddressByIndex(C_GOVERNOR));
token = INXMToken(registry.getContractAddressByIndex(C_TOKEN));
}

function balanceOf(address member) public view returns (uint) {
return governor.getVoteWeight(member);
}

ITokenController tokenController = ITokenController(master.getLatestAddress("TC"));
IMemberRoles memberRoles = IMemberRoles(master.getLatestAddress("MR"));
IGovernance governance = IGovernance(master.getLatestAddress("GV"));

if (!memberRoles.checkRole(member, uint(Role.Member))) {
return 0;
}

uint delegationId = governance.followerDelegation(member);

if (delegationId != 0) {
(, address leader,) = governance.allDelegation(delegationId);
if (leader != address(0)) {
return 0;
}
}

uint balance = tokenController.totalBalanceOf(member) + 1e18;
uint[] memory delegationIds = governance.getFollowers(member);

for (uint i = 0; i < delegationIds.length; i++) {

(address follower, address leader,) = governance.allDelegation(delegationIds[i]);

if (
leader != member ||
!memberRoles.checkRole(follower, uint(Role.Member))
) {
continue;
}

balance += tokenController.totalBalanceOf(follower) + 1e18;
}

return balance;
function totalSupply() public view returns (uint) {
return token.totalSupply();
}

}