编译器
0.8.11+commit.d7f03943
文件 1 的 14:AccessControl.sol
pragma solidity ^0.8.10;
import { IAccessControl } from "./IAccessControl.sol";
import { Context } from "./Context.sol";
import { Strings } from "./Strings.sol";
import { ERC165 } from "./ERC165.sol";
import { Ownable } from "./Ownable.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;
modifier onlyRole(bytes32 role) virtual {
_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) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}
文件 2 的 14:Context.sol
pragma solidity ^0.8.10;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 3 的 14:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 4 的 14:IAccessControl.sol
pragma solidity ^0.8.0;
interface IAccessControl {
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);
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;
}
文件 5 的 14:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 6 的 14:IERC20.sol
pragma solidity ^0.8.10;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 7 的 14:IStakingContractV1.sol
pragma solidity ^0.8.11;
interface IStakingContractV1 {
event StakeDeposited(
address indexed staker,
uint256 amount,
string stakerPubKey,
string validatorPubKey);
event UnlockStake(
address indexed staker,
uint256 amount,
string validatorPubKey);
event ForceUnlockStake(
address indexed staker,
uint256 amount,
string validatorPubKey);
event StakeWithdrawn(
address indexed staker,
uint256 stake,
uint256 rewards);
function deposit(
uint256 _amount,
string memory _stakerPubKey,
string memory _validatorPubKey)
external;
function unlockStake(
string memory _stakerPubKey,
uint256 _rewardAmount)
external;
function forceUnlockStake(
string memory _stakerPubKey,
uint256 _rewardAmount)
external;
function withdraw()
external;
function getStatus(
address _stakerEthAddress)
external
returns(uint currentStatus);
function setRatio(
uint256 _newRatio)
external;
function getRatio()
external
view
returns (uint256 newRatio);
function changeMinDeposit(
uint256 _newAmount)
external;
function changeUnlockGasCost(
uint256 _newGasCost)
external;
function changeRewardWallet(
address _newRewardWallet)
external;
function pause()
external;
function unPause()
external;
}
文件 8 的 14:IUniswapV2Pair.sol
pragma solidity >=0.5.0;
interface IUniswapV2Pair {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
文件 9 的 14:Ownable.sol
pragma solidity ^0.8.10;
import { Context } from "./Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
文件 10 的 14:Pausable.sol
pragma solidity ^0.8.11;
import { Context } from "./Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor () {
_paused = false;
}
function paused() public view virtual returns (bool) {
return _paused;
}
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 11 的 14:StakeOpsController.sol
pragma solidity ^0.8.11;
import { AccessControl } from "./AccessControl.sol";
contract StakeOpsController is AccessControl {
bytes32 public constant STAKE_OPS_ADMIN_ROLE = keccak256("STAKE_OPS_ADMIN_ROLE");
bytes32 public constant BALANCE_UPDATER_ROLE = keccak256("BALANCE_UPDATER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
constructor(
address _stakeOpsAdmin,
address _balanceUpdater,
address _pauser) {
require(_stakeOpsAdmin != _balanceUpdater, "StakeOpsController: Accounts must be different");
require(_balanceUpdater != _pauser, "StakeOpsController: Accounts must be different");
_setRoleAdmin(STAKE_OPS_ADMIN_ROLE, STAKE_OPS_ADMIN_ROLE);
_setRoleAdmin(BALANCE_UPDATER_ROLE, STAKE_OPS_ADMIN_ROLE);
_setRoleAdmin(PAUSER_ROLE, STAKE_OPS_ADMIN_ROLE);
_setupRole(STAKE_OPS_ADMIN_ROLE, _stakeOpsAdmin);
_setupRole(BALANCE_UPDATER_ROLE, _stakeOpsAdmin);
_setupRole(PAUSER_ROLE, _stakeOpsAdmin);
_setupRole(BALANCE_UPDATER_ROLE, _balanceUpdater);
_setupRole(PAUSER_ROLE, _pauser);
}
modifier onlyRole(bytes32 role) override {
require(hasRole(role, _msgSender()) || hasRole(role, address(0)), "StakeOpsController: sender requires permission");
_;
}
}
文件 12 的 14:StakeStructs.sol
pragma solidity ^0.8.11;
contract StakeStructs {
enum StakeStatus { NeverStaked, Deposited, Unstaked, Withdrawn }
struct StakingOpsInfo {
uint256 stakeCount;
uint256 totalStaked;
uint256 minPowrDeposit;
uint256 maxPowrPerValidator;
uint256 powrRatio;
address powrEthPool;
uint256 unlockGasCost;
address rewardWallet;
}
struct StakeInfo {
uint256 stake;
uint256 stakeRewards;
string registeredStaker;
string registeredStakerValidatorPubKey;
StakeStatus stakeStatus;
uint256 ethFee;
uint256 unstakeTimestamp;
}
}
文件 13 的 14:StakingContractV1.sol
pragma solidity ^0.8.11;
import { IUniswapV2Pair } from "./IUniswapV2Pair.sol";
import { IERC20 } from "./IERC20.sol";
import { IStakingContractV1 } from "./IStakingContractV1.sol";
import { Pausable } from "./Pausable.sol";
import { StakeStructs } from "./StakeStructs.sol";
import { StakeOpsController } from "./StakeOpsController.sol";
import { Context } from "./Context.sol";
contract StakingContractV1 is StakeStructs, IStakingContractV1, StakeOpsController, Pausable {
IERC20 public immutable powrToken;
uint256 public constant unit = 1000000;
StakeStructs.StakingOpsInfo public stkOpsData;
mapping(address => StakeStructs.StakeInfo) public stkData;
mapping(string => uint256) public validatorTotalStake;
mapping (string => address) public stakeAddressToEthAddress;
modifier checkDepositConditions(
address _addr,
uint256 _amount,
string memory _stakerPubKey,
string memory _validatorPubKey) {
require(_amount > 0, "StakingContractV1:checkDepositConditions: Amount must be > 0");
require(_amount >= stkOpsData.minPowrDeposit, "StakingContractV1:checkDepositConditions: Amount must be at least the min deposit requirement");
require(validatorTotalStake[_validatorPubKey] + _amount <= stkOpsData.maxPowrPerValidator, "StakingContractV1:checkDepositConditions: Total stake cannot exceed max stake per validator");
require(stkData[_addr].stakeStatus == StakeStatus.NeverStaked, "StakingContractV1:checkDepositConditions: Address can only stake once");
require(stakeAddressToEthAddress[_stakerPubKey] == address(0), "StakingContractV1:checkDepositConditions: Solana wallet can only stake once");
_;
}
modifier checkWithdrawalConditions(address _addr) {
require(stkData[_addr].stakeStatus != StakeStatus.Withdrawn, "StakingContractV1:checkWithdrawalConditions: Stake already withdrawn");
require(stkData[_addr].stakeStatus == StakeStatus.Unstaked, "StakingContractV1:checkWithdrawalConditions: Stake has not been unstaked or cannot be found");
require(stkData[_addr].stake + stkData[_addr].stakeRewards > 0, "StakingContractV1:checkWithdrawalConditions: No stake to withdraw");
require(block.timestamp >= (stkData[_addr].unstakeTimestamp + (7*24*60*60)), "StakingContractV1:checkWithdrawalConditions: 7 days need to pass before you can withdraw");
_;
}
constructor(
address _powrToken,
uint256 _minPowrDeposit,
uint256 _maxPowrPerValidator,
address _stakeOpsAdmin,
address _balanceUpdater,
address _pauser,
address _powrEthPoolAddress,
uint256 _unlockGasCost,
address _rewardWallet)
StakeOpsController(
_stakeOpsAdmin,
_balanceUpdater,
_pauser){
require(_powrToken != address(0), "StakingContractV1: _powrToken address is incorrect");
powrToken = IERC20(_powrToken);
stkOpsData.minPowrDeposit = _minPowrDeposit * unit;
stkOpsData.maxPowrPerValidator = _maxPowrPerValidator * unit;
stkOpsData.powrRatio = 10000;
stkOpsData.powrEthPool = _powrEthPoolAddress;
stkOpsData.unlockGasCost = _unlockGasCost;
stkOpsData.rewardWallet = _rewardWallet;
}
function deposit(
uint256 _amount,
string memory _stakerPubKey,
string memory _validatorPubKey)
external
whenNotPaused
checkDepositConditions(_msgSender(), _amount, _stakerPubKey, _validatorPubKey)
{
address stakerEthAddress = _msgSender();
require(powrToken.transferFrom(stakerEthAddress, address(this), _amount), "StakingContractV1:deposit: Can't transfer the POWR tokens");
stkData[stakerEthAddress] = StakeStructs.StakeInfo({
stake: _amount,
stakeRewards: 0,
registeredStaker: _stakerPubKey,
registeredStakerValidatorPubKey: _validatorPubKey,
stakeStatus: StakeStatus.Deposited,
ethFee: 0,
unstakeTimestamp: 0
});
stakeAddressToEthAddress[_stakerPubKey] = stakerEthAddress;
validatorTotalStake[_validatorPubKey] = validatorTotalStake[_validatorPubKey] + _amount;
stkOpsData.stakeCount = stkOpsData.stakeCount + 1;
stkOpsData.totalStaked = stkOpsData.totalStaked + _amount;
emit StakeDeposited(stakerEthAddress, _amount, _stakerPubKey, _validatorPubKey);
}
function unlockStake(
string memory _stakerPubKey,
uint256 _rewardAmount)
external
whenNotPaused
onlyRole(BALANCE_UPDATER_ROLE)
{
address stakerEthAddress = stakeAddressToEthAddress[_stakerPubKey];
require(stkData[stakerEthAddress].stakeStatus == StakeStatus.Deposited, "StakingContractV1:unlockStake Stake must be in 'deposited' state");
stkData[stakerEthAddress].stakeStatus = StakeStatus.Unstaked;
stkData[stakerEthAddress].stakeRewards = _rewardAmount;
stkData[stakerEthAddress].ethFee = stkOpsData.unlockGasCost*tx.gasprice;
stkData[stakerEthAddress].unstakeTimestamp = block.timestamp;
stkOpsData.stakeCount = stkOpsData.stakeCount - 1;
stkOpsData.totalStaked = stkOpsData.totalStaked - stkData[stakerEthAddress].stake;
validatorTotalStake[stkData[stakerEthAddress].registeredStakerValidatorPubKey] = validatorTotalStake[stkData[stakerEthAddress].registeredStakerValidatorPubKey] - stkData[stakerEthAddress].stake;
emit UnlockStake(stakerEthAddress, stkData[stakerEthAddress].stake, stkData[stakerEthAddress].registeredStaker);
}
function withdraw()
external
whenNotPaused
checkWithdrawalConditions(_msgSender()){
address stakerEthAddress = _msgSender();
uint256 stakeAmount = stkData[stakerEthAddress].stake;
uint256 rewardAmount = stkData[stakerEthAddress].stakeRewards * stkOpsData.powrRatio / 10000;
uint256 powrFee = uint(convertEthToPOWR(stkData[stakerEthAddress].ethFee));
stkData[stakerEthAddress].stake = 0;
stkData[stakerEthAddress].stakeRewards = 0;
stkData[stakerEthAddress].stakeStatus = StakeStatus.Withdrawn;
if(powrFee >= rewardAmount) {
uint256 remainingFee = powrFee - rewardAmount;
require(stakeAmount >= remainingFee, "StakingContractV1:withdraw Not enough POWR in stake to cover withdrawal fee");
uint256 remainingStake = stakeAmount - remainingFee;
require(powrToken.transfer(stakerEthAddress, remainingStake), "StakingContractV1:withdraw Can't transfer remaining POWR tokens staking contract");
require(powrToken.transfer(stkOpsData.rewardWallet, stakeAmount - remainingStake), "StakingContractV1:withdraw Can't transfer POWR fee from staking contract");
} else {
require(powrToken.transfer(stakerEthAddress, stakeAmount), "StakingContractV1:withdraw Can't transfer POWR tokens from staking contract");
require(powrToken.transferFrom(stkOpsData.rewardWallet, stakerEthAddress, rewardAmount - powrFee), "StakingContractV1:withdraw Can't transfer POWR tokens from admin account");
}
emit StakeWithdrawn(stakerEthAddress, stakeAmount, rewardAmount);
}
function forceUnlockStake(
string memory _stakerPubKey,
uint256 _rewardAmount)
external
onlyRole(STAKE_OPS_ADMIN_ROLE)
{
address stakerEthAddress = stakeAddressToEthAddress[_stakerPubKey];
require(stkData[stakerEthAddress].stakeStatus == StakeStatus.Deposited || stkData[stakerEthAddress].stakeStatus == StakeStatus.Unstaked, "StakingContractV1:forceUnlockStake: Stake must be in 'deposited' or 'unstaked' state");
stkData[stakerEthAddress].stakeStatus = StakeStatus.Unstaked;
stkData[stakerEthAddress].stakeRewards = _rewardAmount;
stkData[stakerEthAddress].ethFee = stkOpsData.unlockGasCost*tx.gasprice;
stkData[stakerEthAddress].unstakeTimestamp = block.timestamp;
stkOpsData.stakeCount = stkOpsData.stakeCount - 1;
stkOpsData.totalStaked = stkOpsData.totalStaked - stkData[stakerEthAddress].stake;
validatorTotalStake[stkData[stakerEthAddress].registeredStakerValidatorPubKey] = validatorTotalStake[stkData[stakerEthAddress].registeredStakerValidatorPubKey] - stkData[stakerEthAddress].stake;
emit ForceUnlockStake(stakerEthAddress, stkData[stakerEthAddress].stake, stkData[stakerEthAddress].registeredStaker);
}
function getStatus(address _stakerEthAddress)
external
view
returns(uint currentStatus)
{
currentStatus = uint(stkData[_stakerEthAddress].stakeStatus);
return(currentStatus);
}
function convertEthToPOWR(uint256 _ethAmount)
public
view
returns(uint256 powrAmount)
{
IUniswapV2Pair pair = IUniswapV2Pair(stkOpsData.powrEthPool);
(uint112 powrReserves, uint112 ethReserves,) = pair.getReserves();
powrAmount = (_ethAmount*powrReserves)/(ethReserves);
return(powrAmount);
}
function setRatio(
uint256 _newRatio)
external
onlyRole(STAKE_OPS_ADMIN_ROLE)
{
require(_newRatio <= 100000, "New Ratio must be <= 100000");
stkOpsData.powrRatio = _newRatio;
}
function getRatio()
external
view
returns (uint256 currentRatio)
{
currentRatio = stkOpsData.powrRatio;
return(currentRatio);
}
function changeMinDeposit(uint256 _newAmount)
external
onlyRole(STAKE_OPS_ADMIN_ROLE){
stkOpsData.minPowrDeposit = _newAmount * unit;
}
function changeUnlockGasCost(uint256 _newGasCost)
external
onlyRole(STAKE_OPS_ADMIN_ROLE){
stkOpsData.unlockGasCost = _newGasCost;
}
function changeRewardWallet(address _newRewardWallet)
external
onlyRole(STAKE_OPS_ADMIN_ROLE){
stkOpsData.rewardWallet = _newRewardWallet;
}
function pause()
external
onlyRole(PAUSER_ROLE) {
_pause();
}
function unPause()
external
onlyRole(PAUSER_ROLE) {
_unpause();
}
}
文件 14 的 14: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": {
"StakingContractV1.sol": "StakingContractV1"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_powrToken","type":"address"},{"internalType":"uint256","name":"_minPowrDeposit","type":"uint256"},{"internalType":"uint256","name":"_maxPowrPerValidator","type":"uint256"},{"internalType":"address","name":"_stakeOpsAdmin","type":"address"},{"internalType":"address","name":"_balanceUpdater","type":"address"},{"internalType":"address","name":"_pauser","type":"address"},{"internalType":"address","name":"_powrEthPoolAddress","type":"address"},{"internalType":"uint256","name":"_unlockGasCost","type":"uint256"},{"internalType":"address","name":"_rewardWallet","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"string","name":"validatorPubKey","type":"string"}],"name":"ForceUnlockStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"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":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"string","name":"stakerPubKey","type":"string"},{"indexed":false,"internalType":"string","name":"validatorPubKey","type":"string"}],"name":"StakeDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"stake","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewards","type":"uint256"}],"name":"StakeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"string","name":"validatorPubKey","type":"string"}],"name":"UnlockStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"BALANCE_UPDATER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKE_OPS_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newAmount","type":"uint256"}],"name":"changeMinDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newRewardWallet","type":"address"}],"name":"changeRewardWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newGasCost","type":"uint256"}],"name":"changeUnlockGasCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ethAmount","type":"uint256"}],"name":"convertEthToPOWR","outputs":[{"internalType":"uint256","name":"powrAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"string","name":"_stakerPubKey","type":"string"},{"internalType":"string","name":"_validatorPubKey","type":"string"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_stakerPubKey","type":"string"},{"internalType":"uint256","name":"_rewardAmount","type":"uint256"}],"name":"forceUnlockStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRatio","outputs":[{"internalType":"uint256","name":"currentRatio","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":"address","name":"_stakerEthAddress","type":"address"}],"name":"getStatus","outputs":[{"internalType":"uint256","name":"currentStatus","type":"uint256"}],"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":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"powrToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","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":"uint256","name":"_newRatio","type":"uint256"}],"name":"setRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"stakeAddressToEthAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stkData","outputs":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"stakeRewards","type":"uint256"},{"internalType":"string","name":"registeredStaker","type":"string"},{"internalType":"string","name":"registeredStakerValidatorPubKey","type":"string"},{"internalType":"enum StakeStructs.StakeStatus","name":"stakeStatus","type":"uint8"},{"internalType":"uint256","name":"ethFee","type":"uint256"},{"internalType":"uint256","name":"unstakeTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stkOpsData","outputs":[{"internalType":"uint256","name":"stakeCount","type":"uint256"},{"internalType":"uint256","name":"totalStaked","type":"uint256"},{"internalType":"uint256","name":"minPowrDeposit","type":"uint256"},{"internalType":"uint256","name":"maxPowrPerValidator","type":"uint256"},{"internalType":"uint256","name":"powrRatio","type":"uint256"},{"internalType":"address","name":"powrEthPool","type":"address"},{"internalType":"uint256","name":"unlockGasCost","type":"uint256"},{"internalType":"address","name":"rewardWallet","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_stakerPubKey","type":"string"},{"internalType":"uint256","name":"_rewardAmount","type":"uint256"}],"name":"unlockStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"validatorTotalStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]