文件 1 的 15:AccessControl.sol
pragma solidity ^0.8.0;
import "../interfaces/IAccessControl.sol";
import "./Context.sol";
import "./Strings.sol";
import "./ERC165.sol";
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
modifier onlyRole(bytes32 role) {
_checkRole(role, _msgSender());
_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _roles[role].members[account];
}
function _checkRole(bytes32 role, address account) internal view {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(uint160(account), 20),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _grantRole(bytes32 role, address account) private {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) internal {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}
文件 2 的 15:AccessControlEnumerable.sol
pragma solidity ^0.8.0;
import "../interfaces/IAccessControlEnumerable.sol";
import "./AccessControl.sol";
import "./EnumerableSet.sol";
abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {
using EnumerableSet for EnumerableSet.AddressSet;
mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);
}
function getRoleMember(bytes32 role, uint256 index) public view override returns (address) {
return _roleMembers[role].at(index);
}
function getRoleMemberCount(bytes32 role) public view override returns (uint256) {
return _roleMembers[role].length();
}
function grantRole(bytes32 role, address account) public virtual override {
super.grantRole(role, account);
_roleMembers[role].add(account);
}
function revokeRole(bytes32 role, address account) public virtual override {
super.revokeRole(role, account);
_roleMembers[role].remove(account);
}
function renounceRole(bytes32 role, address account) public virtual override {
super.renounceRole(role, account);
_roleMembers[role].remove(account);
}
function _setupRole(bytes32 role, address account) internal virtual override {
super._setupRole(role, account);
_roleMembers[role].add(account);
}
}
文件 3 的 15:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 4 的 15:ERC165.sol
pragma solidity ^0.8.0;
import "../interfaces/IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 5 的 15:EnumerableSet.sol
pragma solidity ^0.8.0;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping(bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastvalue = set._values[lastIndex];
set._values[toDeleteIndex] = lastvalue;
set._indexes[lastvalue] = valueIndex;
}
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
}
文件 6 的 15:IAccessControl.sol
pragma solidity ^0.8.0;
interface IAccessControl {
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 7 的 15:IAccessControlEnumerable.sol
pragma solidity ^0.8.0;
interface IAccessControlEnumerable {
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
function getRoleMemberCount(bytes32 role) external view returns (uint256);
}
文件 8 的 15:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 9 的 15:ILockManager.sol
pragma solidity ^0.8.0;
interface ILockManager {
struct LockedStake {
uint256 amount;
uint256 votingPower;
}
function getAmountStaked(address staker, address stakedToken) external view returns (uint256);
function getStake(address staker, address stakedToken) external view returns (LockedStake memory);
function calculateVotingPower(address token, uint256 amount) external view returns (uint256);
function grantVotingPower(address receiver, address token, uint256 tokenAmount) external returns (uint256 votingPowerGranted);
function removeVotingPower(address receiver, address token, uint256 tokenAmount) external returns (uint256 votingPowerRemoved);
}
文件 10 的 15:ITokenRegistry.sol
pragma solidity ^0.8.0;
interface ITokenRegistry {
function owner() external view returns (address);
function tokenFormulas(address) external view returns (address);
function setTokenFormula(address token, address formula) external;
function removeToken(address token) external;
function changeOwner(address newOwner) external;
event ChangedOwner(address indexed oldOwner, address indexed newOwner);
event TokenAdded(address indexed token, address indexed formula);
event TokenRemoved(address indexed token);
event TokenFormulaUpdated(address indexed token, address indexed formula);
}
文件 11 的 15:IVotingPower.sol
pragma solidity ^0.8.0;
import "../lib/PrismProxy.sol";
interface IVotingPower {
struct Stake {
uint256 amount;
uint256 votingPower;
}
function setPendingProxyImplementation(address newPendingImplementation) external returns (bool);
function acceptProxyImplementation() external returns (bool);
function setPendingProxyAdmin(address newPendingAdmin) external returns (bool);
function acceptProxyAdmin() external returns (bool);
function proxyAdmin() external view returns (address);
function pendingProxyAdmin() external view returns (address);
function proxyImplementation() external view returns (address);
function pendingProxyImplementation() external view returns (address);
function proxyImplementationVersion() external view returns (uint8);
function become(PrismProxy prism) external;
function initialize(address _edenToken, address _owner) external;
function owner() external view returns (address);
function edenToken() external view returns (address);
function tokenRegistry() external view returns (address);
function lockManager() external view returns (address);
function changeOwner(address newOwner) external;
function setTokenRegistry(address registry) external;
function setLockManager(address newLockManager) external;
function stake(uint256 amount) external;
function stakeWithPermit(uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
function withdraw(uint256 amount) external;
function addVotingPowerForLockedTokens(address account, uint256 amount) external;
function removeVotingPowerForUnlockedTokens(address account, uint256 amount) external;
function getEDENAmountStaked(address staker) external view returns (uint256);
function getAmountStaked(address staker, address stakedToken) external view returns (uint256);
function getEDENStake(address staker) external view returns (Stake memory);
function getStake(address staker, address stakedToken) external view returns (Stake memory);
function balanceOf(address account) external view returns (uint256);
function balanceOfAt(address account, uint256 blockNumber) external view returns (uint256);
event NewPendingImplementation(address indexed oldPendingImplementation, address indexed newPendingImplementation);
event NewImplementation(address indexed oldImplementation, address indexed newImplementation);
event NewPendingAdmin(address indexed oldPendingAdmin, address indexed newPendingAdmin);
event NewAdmin(address indexed oldAdmin, address indexed newAdmin);
event Staked(address indexed user, address indexed token, uint256 indexed amount, uint256 votingPower);
event Withdrawn(address indexed user, address indexed token, uint256 indexed amount, uint256 votingPower);
event VotingPowerChanged(address indexed voter, uint256 indexed previousBalance, uint256 indexed newBalance);
}
文件 12 的 15:IVotingPowerFormula.sol
pragma solidity ^0.8.0;
interface IVotingPowerFormula {
function convertTokensToVotingPower(uint256 amount) external view returns (uint256);
}
文件 13 的 15:LockManager.sol
pragma solidity ^0.8.0;
import "./interfaces/IVotingPower.sol";
import "./interfaces/ITokenRegistry.sol";
import "./interfaces/IVotingPowerFormula.sol";
import "./interfaces/ILockManager.sol";
import "./lib/AccessControlEnumerable.sol";
contract LockManager is AccessControlEnumerable, ILockManager {
bytes32 public constant LOCKER_ROLE = keccak256("LOCKER_ROLE");
mapping (address => mapping (address => LockedStake)) internal lockedStakes;
IVotingPower public immutable votingPower;
modifier onlyLockers() {
require(hasRole(LOCKER_ROLE, msg.sender), "Caller must have LOCKER_ROLE role");
_;
}
event StakeLocked(address indexed user, address indexed token, uint256 indexed amount, uint256 votingPower);
event StakeUnlocked(address indexed user, address indexed token, uint256 indexed amount, uint256 votingPower);
constructor(address _votingPower, address _roleManager) {
votingPower = IVotingPower(_votingPower);
_setupRole(DEFAULT_ADMIN_ROLE, _roleManager);
}
function getAmountStaked(address staker, address stakedToken) external view override returns (uint256) {
return getStake(staker, stakedToken).amount;
}
function getStake(address staker, address stakedToken) public view override returns (LockedStake memory) {
return lockedStakes[staker][stakedToken];
}
function calculateVotingPower(address token, uint256 amount) public view override returns (uint256) {
address registry = votingPower.tokenRegistry();
require(registry != address(0), "LM::calculateVotingPower: registry not set");
address tokenFormulaAddress = ITokenRegistry(registry).tokenFormulas(token);
require(tokenFormulaAddress != address(0), "LM::calculateVotingPower: token not supported");
IVotingPowerFormula tokenFormula = IVotingPowerFormula(tokenFormulaAddress);
return tokenFormula.convertTokensToVotingPower(amount);
}
function grantVotingPower(
address receiver,
address token,
uint256 tokenAmount
) external override onlyLockers returns (uint256 votingPowerGranted){
votingPowerGranted = calculateVotingPower(token, tokenAmount);
lockedStakes[receiver][token].amount = lockedStakes[receiver][token].amount + tokenAmount;
lockedStakes[receiver][token].votingPower = lockedStakes[receiver][token].votingPower + votingPowerGranted;
votingPower.addVotingPowerForLockedTokens(receiver, votingPowerGranted);
emit StakeLocked(receiver, token, tokenAmount, votingPowerGranted);
}
function removeVotingPower(
address receiver,
address token,
uint256 tokenAmount
) external override onlyLockers returns (uint256 votingPowerRemoved) {
require(lockedStakes[receiver][token].amount >= tokenAmount, "LM::removeVotingPower: not enough tokens staked");
LockedStake memory s = getStake(receiver, token);
votingPowerRemoved = tokenAmount * s.votingPower / s.amount;
lockedStakes[receiver][token].amount = lockedStakes[receiver][token].amount - tokenAmount;
lockedStakes[receiver][token].votingPower = lockedStakes[receiver][token].votingPower - votingPowerRemoved;
votingPower.removeVotingPowerForUnlockedTokens(receiver, votingPowerRemoved);
emit StakeUnlocked(receiver, token, tokenAmount, votingPowerRemoved);
}
}
文件 14 的 15:PrismProxy.sol
pragma solidity ^0.8.0;
contract PrismProxy {
struct ProxyStorage {
address admin;
address pendingAdmin;
address implementation;
address pendingImplementation;
uint8 version;
}
bytes32 constant PRISM_PROXY_STORAGE_POSITION = keccak256("prism.proxy.storage");
event NewPendingImplementation(address indexed oldPendingImplementation, address indexed newPendingImplementation);
event NewImplementation(address indexed oldImplementation, address indexed newImplementation);
event NewPendingAdmin(address indexed oldPendingAdmin, address indexed newPendingAdmin);
event NewAdmin(address indexed oldAdmin, address indexed newAdmin);
function proxyStorage() internal pure returns (ProxyStorage storage ps) {
bytes32 position = PRISM_PROXY_STORAGE_POSITION;
assembly {
ps.slot := position
}
}
function setPendingProxyImplementation(address newPendingImplementation) public returns (bool) {
ProxyStorage storage s = proxyStorage();
require(msg.sender == s.admin, "Prism::setPendingProxyImp: caller must be admin");
address oldPendingImplementation = s.pendingImplementation;
s.pendingImplementation = newPendingImplementation;
emit NewPendingImplementation(oldPendingImplementation, s.pendingImplementation);
return true;
}
function acceptProxyImplementation() public returns (bool) {
ProxyStorage storage s = proxyStorage();
require(msg.sender == s.pendingImplementation && s.pendingImplementation != address(0), "Prism::acceptProxyImp: caller must be pending implementation");
address oldImplementation = s.implementation;
address oldPendingImplementation = s.pendingImplementation;
s.implementation = s.pendingImplementation;
s.pendingImplementation = address(0);
s.version++;
emit NewImplementation(oldImplementation, s.implementation);
emit NewPendingImplementation(oldPendingImplementation, s.pendingImplementation);
return true;
}
function setPendingProxyAdmin(address newPendingAdmin) public returns (bool) {
ProxyStorage storage s = proxyStorage();
require(msg.sender == s.admin, "Prism::setPendingProxyAdmin: caller must be admin");
address oldPendingAdmin = s.pendingAdmin;
s.pendingAdmin = newPendingAdmin;
emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);
return true;
}
function acceptProxyAdmin() public returns (bool) {
ProxyStorage storage s = proxyStorage();
require(msg.sender == s.pendingAdmin && msg.sender != address(0), "Prism::acceptProxyAdmin: caller must be pending admin");
address oldAdmin = s.admin;
address oldPendingAdmin = s.pendingAdmin;
s.admin = s.pendingAdmin;
s.pendingAdmin = address(0);
emit NewAdmin(oldAdmin, s.admin);
emit NewPendingAdmin(oldPendingAdmin, s.pendingAdmin);
return true;
}
function proxyAdmin() public view returns (address) {
ProxyStorage storage s = proxyStorage();
return s.admin;
}
function pendingProxyAdmin() public view returns (address) {
ProxyStorage storage s = proxyStorage();
return s.pendingAdmin;
}
function proxyImplementation() public view returns (address) {
ProxyStorage storage s = proxyStorage();
return s.implementation;
}
function pendingProxyImplementation() public view returns (address) {
ProxyStorage storage s = proxyStorage();
return s.pendingImplementation;
}
function proxyImplementationVersion() public view returns (uint8) {
ProxyStorage storage s = proxyStorage();
return s.version;
}
function _forwardToImplementation() internal {
ProxyStorage storage s = proxyStorage();
(bool success, ) = s.implementation.delegatecall(msg.data);
assembly {
let free_mem_ptr := mload(0x40)
returndatacopy(free_mem_ptr, 0, returndatasize())
switch success
case 0 { revert(free_mem_ptr, returndatasize()) }
default { return(free_mem_ptr, returndatasize()) }
}
}
}
文件 15 的 15:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
{
"compilationTarget": {
"contracts/LockManager.sol": "LockManager"
},
"evmVersion": "berlin",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 999999
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_votingPower","type":"address"},{"internalType":"address","name":"_roleManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"votingPower","type":"uint256"}],"name":"StakeLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"votingPower","type":"uint256"}],"name":"StakeUnlocked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCKER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"calculateVotingPower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"stakedToken","type":"address"}],"name":"getAmountStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"stakedToken","type":"address"}],"name":"getStake","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"votingPower","type":"uint256"}],"internalType":"struct ILockManager.LockedStake","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"grantVotingPower","outputs":[{"internalType":"uint256","name":"votingPowerGranted","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"removeVotingPower","outputs":[{"internalType":"uint256","name":"votingPowerRemoved","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votingPower","outputs":[{"internalType":"contract IVotingPower","name":"","type":"address"}],"stateMutability":"view","type":"function"}]