ETH Price: $2,863.65 (-2.64%)
 

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Claim413068762026-01-26 4:51:391 min ago1769403099IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000430.00469026
Claim413067432026-01-26 4:47:135 mins ago1769402833IN
0x2Fb46818...6FCc58DB0
0 ETH0.00000050.00545427
Claim413066802026-01-26 4:45:077 mins ago1769402707IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000370.00496867
Claim413066802026-01-26 4:45:077 mins ago1769402707IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000450.00496867
Claim413066692026-01-26 4:44:458 mins ago1769402685IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000380.00508597
Claim413065902026-01-26 4:42:0710 mins ago1769402527IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000370.00503229
Claim413065032026-01-26 4:39:1313 mins ago1769402353IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000380.00508025
Claim413064612026-01-26 4:37:4915 mins ago1769402269IN
0x2Fb46818...6FCc58DB0
0 ETH0.00000040.00535713
Claim413064072026-01-26 4:36:0116 mins ago1769402161IN
0x2Fb46818...6FCc58DB0
0 ETH0.00000050.00545532
Claim413062502026-01-26 4:30:4722 mins ago1769401847IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000490.00535524
Claim413059842026-01-26 4:21:5530 mins ago1769401315IN
0x2Fb46818...6FCc58DB0
0 ETH0.00000060.00649301
Claim413058772026-01-26 4:18:2134 mins ago1769401101IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000520.00567118
Claim413057452026-01-26 4:13:5738 mins ago1769400837IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000430.0057743
Claim413056982026-01-26 4:12:2340 mins ago1769400743IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000440.00597264
Claim413056252026-01-26 4:09:5742 mins ago1769400597IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000450.00603608
Claim413054892026-01-26 4:05:2547 mins ago1769400325IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000610.00662191
Claim413054042026-01-26 4:02:3550 mins ago1769400155IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000640.00701887
Claim413053842026-01-26 4:01:5550 mins ago1769400115IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000640.00701083
Claim413053792026-01-26 4:01:4551 mins ago1769400105IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000520.00696909
Claim413053482026-01-26 4:00:4352 mins ago1769400043IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000630.0068733
Claim413052682026-01-26 3:58:0354 mins ago1769399883IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000540.00727081
Claim413051502026-01-26 3:54:0758 mins ago1769399647IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000660.00720197
Claim413050962026-01-26 3:52:191 hr ago1769399539IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000680.00745804
Claim413050752026-01-26 3:51:371 hr ago1769399497IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000570.00761022
Claim413049842026-01-26 3:48:351 hr ago1769399315IN
0x2Fb46818...6FCc58DB0
0 ETH0.000000750.008146
View all transactions

Parent Transaction Hash Block From To
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BETRRewards

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 200 runs

Other Settings:
cancun EvmVersion, MIT license
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Ownable} from "./common/Ownable.sol";
import {IBETRStakingEventHandler} from "./interfaces/IBETRStakingEventHandler.sol";
import {IBETRStakingStateProvider} from "./interfaces/IBETRStakingStateProvider.sol";
import {InvalidInput, TokensTransferError} from "./common/error.sol";

/*
 * @title BETRRewards
 * @author Mirko Nosenzo (@netnose)
 * @notice This contract is used to manage rewards for the staking contract
 */
contract BETRRewards is IBETRStakingEventHandler, Ownable {
    mapping(address => uint256) private _debts;
    mapping(address => uint256) private _credits;

    uint256 public constant PRECISION = 1e18;

    IBETRStakingStateProvider public stakingContract;
    IERC20 public rewardToken;
    uint256 public rewardAccumulatedPerStakedToken;
    uint256 public totalRewardsClaimed;
    uint256 public totalRewardsClaimable;
    bool public isRewardingPaused;

    /*
     * @notice Constructor
     * @param _owner The owner of the contract
     * @param _stakingContract The address of the staking contract
     * @param _rewardToken The address of the reward token
     */
    constructor(address _owner, address _stakingContract, address _rewardToken) Ownable(_owner) {
        if (_stakingContract == address(0)) revert InvalidInput();
        if (_rewardToken == address(0)) revert InvalidInput();

        stakingContract = IBETRStakingStateProvider(_stakingContract);
        rewardToken = IERC20(_rewardToken);
    }

    /*
     * @title RewardingPaused
     * @notice Error to check if the rewarding is paused
     */
    error RewardingPaused();

    /*
     * @title NoClaimableReward
     * @notice Error to check if there is no claimable reward
     * @param _staker The address of the staker
     */
    error NoClaimableReward(address _staker);

    /*
     * @title NoStakedAmount
     * @notice Error to check if there is no staked amount
     */
    error NoStakedAmount();

    /*
     * @title NotStakingContract
     * @notice Error to check if the caller is not the staking contract
     */
    error NotStakingContract();

    /*
     * @title StakingContractNotRewarder
     * @notice Error to check if the caller is not a rewarder
     */
    error StakingContractNotRewarder();

    /*
     * @title RewardingPausedSet
     * @notice Event to notify when the rewarding is paused
     * @param _isRewardingPaused The new rewarding paused state
     */
    event RewardingPausedSet(bool indexed _isRewardingPaused);

    /*
     * @title RewardAdded
     * @notice Event to notify when a reward is added
     * @param _amount The amount of the reward
     */
    event RewardAdded(uint256 _amount);

    /*
     * @title RewardClaimed
     * @notice Event to notify when a reward is claimed
     * @param _staker The address of the staker
     * @param _amount The amount of the reward
     */
    event RewardClaimed(address indexed _staker, uint256 _amount);

    /*
     * @title onlyStakingContract
     * @notice Modifier to check if the caller is the staking contract
     */
    modifier onlyStakingContract() {
        if (msg.sender != address(stakingContract)) revert NotStakingContract();
        _;
    }

    /*
     * @title _claim
     * @notice Function to claim a reward
     * @param _user The address of the user
     */
    function _claim(address _user, uint256 _stakedAmount) internal {
        if (_user == address(0)) revert InvalidInput();

        uint256 rewardAmount = rewardAccumulatedPerStakedToken * _stakedAmount / PRECISION;
        uint256 actualRewardAmount = rewardAmount - _debts[_user] + _credits[_user];
        if (actualRewardAmount == 0) revert NoClaimableReward(_user);

        _debts[_user] = rewardAmount;
        _credits[_user] = 0;
        totalRewardsClaimed += actualRewardAmount;
        totalRewardsClaimable -= actualRewardAmount;

        try rewardToken.transfer(_user, actualRewardAmount) returns (bool success) {
            if (!success) revert TokensTransferError();
        } catch {
            revert TokensTransferError();
        }
        
        emit RewardClaimed(_user, actualRewardAmount);
    }

    /*
     * @title claimable
     * @notice Function to get the claimable rewards for a staker
     * @param _staker The address of the staker
     * @return _amount The amount of the claimable rewards
     */
    function claimable(address _staker) public view returns (uint256 _amount) {
        uint256 rewardAmount = rewardAccumulatedPerStakedToken * stakingContract.stakedAmount(_staker) / PRECISION;
        uint256 actualRewardAmount = rewardAmount - _debts[_staker] + _credits[_staker];
        return actualRewardAmount;
    }

    /*
     * @title claimable
     * @notice Function to get the claimable rewards for the caller
     * @return _amount The amount of the claimable rewards
     */
    function claimable() public view returns (uint256 _amount) {
        return claimable(msg.sender);
    }

    /*
     * @title addReward
     * @notice Function to add a reward
     * @param _amount The amount of the reward
     */
    function addReward(uint256 _amount) public {
        if (isRewardingPaused) revert RewardingPaused();
        if (_amount == 0) revert InvalidInput();
        if (!stakingContract.isRewarder(address(this))) revert StakingContractNotRewarder();

        uint256 totalStakedAmount = stakingContract.totalStakedAmount();
        if (totalStakedAmount == 0) revert NoStakedAmount();

        rewardAccumulatedPerStakedToken += (_amount * PRECISION) / totalStakedAmount;
        totalRewardsClaimable += _amount;

        try rewardToken.transferFrom(msg.sender, address(this), _amount) returns (bool success) {
            if (!success) revert TokensTransferError();
        } catch {
            revert TokensTransferError();
        }

        emit RewardAdded(_amount);
    }

    /*
     * @title claim
     * @notice Function to claim a reward
     */
    function claim() public {
        if (isRewardingPaused) revert RewardingPaused();
        _claim(msg.sender, stakingContract.stakedAmount(msg.sender));
    }

    /*
     * @title batchClaim
     * @notice Admin function to claim all rewards for multiple users (owner only)
     * @param _users Array of addresses of the users to claim rewards for
     * @dev This function bypasses the rewarding pause for emergency situations
     */
    function batchClaim(address[] memory _users) public onlyOwner {
        for (uint256 i = 0; i < _users.length; i++) {
            _claim(_users[i], stakingContract.stakedAmount(_users[i]));
        }
    }

    /*
     * @title setStakingPaused
     * @notice Function to set the staking paused state
     * @param _isRewardingPaused The new rewarding paused state
     */
    function setRewardingPaused(bool _isRewardingPaused) public onlyOwner {
        isRewardingPaused = _isRewardingPaused;
        emit RewardingPausedSet(_isRewardingPaused);
    }

    /*
     * @title onStakeChanged
     * @notice Function to handle the stake changed event
     * @param _user The address of the user
     * @param _oldAmount The old amount of the stake
     * @param _newAmount The new amount of the stake
     */
    function onStakeChanged(address _user, uint256 _oldAmount, uint256 _newAmount) public onlyStakingContract {
        if (_user == address(0)) revert InvalidInput();
        if (_oldAmount == _newAmount) return;

        uint256 rewardAmount = rewardAccumulatedPerStakedToken * _oldAmount / PRECISION;
        uint256 actualRewardAmount = rewardAmount - _debts[_user] + _credits[_user];
        _credits[_user] = actualRewardAmount;
        _debts[_user] = rewardAccumulatedPerStakedToken * _newAmount / PRECISION;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {InvalidInput, TokensTransferError} from "./common/error.sol";
import {Ownable} from "./common/Ownable.sol";
import {IBETRStakingEventHandler} from "./interfaces/IBETRStakingEventHandler.sol";
import {IBETRStakingStateProvider} from "./interfaces/IBETRStakingStateProvider.sol";

/*
 * @title BETRStaking
 * @author Mirko Nosenzo (@netnose)
 * @notice This contract is used to stake an ERC20 token
 */
contract BETRStaking is IBETRStakingStateProvider, Ownable {
    IERC20 public immutable stakingToken;
    uint256 public totalStakedAmount;
    mapping(address => uint256) public stakedAmount;
    bool public isStakingPaused;

    IBETRStakingEventHandler[] public rewarders;

    /*
     * @notice Constructor
     * @param _owner The owner of the contract
     * @param _stakingToken The ERC20 token to stake
     */
    constructor(address _owner, address _stakingToken) Ownable(_owner) {
        if (_stakingToken == address(0)) revert InvalidInput();
        
        stakingToken = IERC20(_stakingToken);
        isStakingPaused = false;
    }

    /*
     * @title NotEnoughStakedAmount
     * @notice Error to check if the staked amount is less than the amount to unstake
     * @param available The available amount
     * @param requested The requested amount
     */
    error NotEnoughStakedAmount(uint256 available, uint256 requested);

    /*
     * @title StakingPaused
     * @notice Error to check if the staking is paused
     */
    error StakingPaused();

    /*
     * @title RewarderAdded
     * @notice Event to notify when a rewarder is added
     * @param rewarder The address of the rewarder
     */
    event RewarderAdded(address indexed rewarder);

    /*
     * @title RewarderRemoved
     * @notice Event to notify when a rewarder is removed
     * @param rewarder The address of the rewarder
     */
    event RewarderRemoved(address indexed rewarder);

    /*
     * @title Staked
     * @notice Event to notify when an address has staked
     * @param staker The address that staked
     * @param amount The amount of tokens staked
     */
    event Staked(address indexed staker, uint256 indexed amount);

    /*
     * @title Unstaked
     * @notice Event to notify when an address has unstaked
     * @param staker The address that unstaked
     * @param amount The amount of tokens unstaked
     */
    event Unstaked(address indexed staker, uint256 indexed amount);

    /*
     * @title StakingPausedSet
     * @notice Event to notify when the staking paused state is set
     * @param isStakingPaused The new staking paused state
     */
    event StakingPausedSet(bool indexed isStakingPaused);

    /*
     * @title _unstake
     * @notice Internal function to unstake tokens for a user
     * @param _user The user to unstake tokens for
     * @param _amount The amount to unstake (0 for all)
     * @return The amount actually unstaked
     */
    function _unstake(address _user, uint256 _amount) internal returns (uint256) {
        if (_user == address(0)) revert InvalidInput();
        
        uint256 userStaked = stakedAmount[_user];
        uint256 amountToUnstake = _amount == 0 ? userStaked : _amount;
        if (amountToUnstake == 0) return 0;

        if (amountToUnstake > userStaked) {
            revert NotEnoughStakedAmount(userStaked, amountToUnstake);
        }
        
        uint256 oldStakedAmount = stakedAmount[_user];
        stakedAmount[_user] -= amountToUnstake;
        uint256 newStakedAmount = stakedAmount[_user];
        for (uint256 i = 0; i < rewarders.length; i++) {
            rewarders[i].onStakeChanged(_user, oldStakedAmount, newStakedAmount);
        }

        try stakingToken.transfer(_user, amountToUnstake) returns (bool success) {
            if (!success) revert TokensTransferError();
        } catch {
            revert TokensTransferError();
        }

        emit Unstaked(_user, amountToUnstake);
        
        return amountToUnstake;
    }

    /*
     * @title stake
     * @notice Stake an ERC20 token
     * @param _amount The amount of ERC20 tokens to stake
     */
    function stake(uint256 _amount) public {
        if (isStakingPaused) revert StakingPaused();
        if (_amount == 0) revert InvalidInput();

        uint256 oldStakedAmount = stakedAmount[msg.sender];
        stakedAmount[msg.sender] += _amount;
        totalStakedAmount += _amount;
        uint256 newStakedAmount = stakedAmount[msg.sender];
        for (uint256 i = 0; i < rewarders.length; i++) {
            rewarders[i].onStakeChanged(msg.sender, oldStakedAmount, newStakedAmount);
        }

        try stakingToken.transferFrom(msg.sender, address(this), _amount) returns (bool success) {
            if (!success) revert TokensTransferError();
        } catch {
            revert TokensTransferError();
        }

        emit Staked(msg.sender, _amount);
    }

    /*
     * @title stakeFor
     * @notice Function to stake tokens for a user
     * @param _user The user to stake tokens for
     * @param _amount The amount of tokens to stake
     */
    function stakeFor(address _user, uint256 _amount) public {
        if (isStakingPaused) revert StakingPaused();
        if (_user == address(0)) revert InvalidInput();
        if (_amount == 0) revert InvalidInput();
        
        uint256 oldStakedAmount = stakedAmount[_user];
        stakedAmount[_user] += _amount;
        totalStakedAmount += _amount;
        uint256 newStakedAmount = stakedAmount[_user];
        for (uint256 i = 0; i < rewarders.length; i++) {
            rewarders[i].onStakeChanged(_user, oldStakedAmount, newStakedAmount);
        }

        try stakingToken.transferFrom(msg.sender, address(this), _amount) returns (bool success) {
            if (!success) revert TokensTransferError();
        } catch {
            revert TokensTransferError();
        }

        emit Staked(_user, _amount);
    }

    /*
     * @title unstake
     * @notice Unstake an ERC20 token
     * @param _amount The amount of ERC20 tokens to unstake
     */
    function unstake(uint256 _amount) public {
        if (isStakingPaused) revert StakingPaused();
        if (_amount == 0) revert InvalidInput();
        
        uint256 unstakedAmount = _unstake(msg.sender, _amount);
        totalStakedAmount -= unstakedAmount;
    }

    /*
     * @title batchUnstake
     * @notice Admin function to unstake tokens for multiple users (owner only)
     * @param _users Array of users to unstake tokens for
     * @param _amounts Array of amounts to unstake (0 for all, must match _users length)
     * @dev This function bypasses the staking pause for emergency situations
     */
    function batchUnstake(address[] calldata _users, uint256[] calldata _amounts) public onlyOwner {
        if (_users.length != _amounts.length) revert InvalidInput();
        if (_users.length == 0) revert InvalidInput();
        
        uint256 totalUnstaked = 0;
        
        for (uint256 i = 0; i < _users.length; i++) {
            address user = _users[i];
            uint256 amount = _amounts[i];
            
            uint256 unstakedAmount = _unstake(user, amount);
            totalUnstaked += unstakedAmount;
        }
        
        totalStakedAmount -= totalUnstaked;
    }

    /*
     * @title setStakingPaused
     * @notice Function to set the staking paused state
     * @param _isStakingPaused The new staking paused state
     */
    function setStakingPaused(bool _isStakingPaused) public onlyOwner {
        isStakingPaused = _isStakingPaused;
        emit StakingPausedSet(_isStakingPaused);
    }

    /*
     * @title isRewarder
     * @notice Function to check if an address is a rewarder
     * @param _rewarder The address of the rewarder
     * @return True if the address is a rewarder, false otherwise
     */
    function isRewarder(address _rewarder) public view returns (bool) {
        for (uint256 i = 0; i < rewarders.length; i++) {
            if (address(rewarders[i]) == _rewarder) {
                return true;
            }
        }
        return false;
    }

    /*
     * @title addRewarder
     * @notice Function to add a rewarder
     * @param _rewarder The address of the rewarder
     */
    function addRewarder(address _rewarder) public onlyOwner {
        if (_rewarder == address(0)) revert InvalidInput();
        if (isRewarder(_rewarder)) revert InvalidInput();
        rewarders.push(IBETRStakingEventHandler(_rewarder));
        emit RewarderAdded(_rewarder);
    }

    /*
     * @title removeRewarder
     * @notice Function to remove a rewarder
     * @param _rewarder The address of the rewarder
     */
    function removeRewarder(address _rewarder) public onlyOwner {
        for (uint256 i = 0; i < rewarders.length; i++) {
            if (address(rewarders[i]) == _rewarder) {
                rewarders[i] = rewarders[rewarders.length - 1];
                rewarders.pop();
                emit RewarderRemoved(_rewarder);
                return;
            }
        }
    }
}

File 4 of 7 : error.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

/*
 * @title InvalidInput
 * @notice Error to check if the input is invalid
 */
error InvalidInput();

/*
 * @title TokensTransferError
 * @notice Error to check if the transfer of tokens fails
 */
error TokensTransferError();

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {InvalidInput} from "./error.sol";

/*
 * @title Ownable
 * @author Mirko Nosenzo (@netnose)
 * @notice This contract is used to manage the ownership of the contract
 */
abstract contract Ownable {
    address public owner;
    address public proposedOwner;

    /*
     * @notice Constructor
     * @param _owner The owner of the contract
     */
    constructor(address _owner) {
        if (_owner == address(0)) revert InvalidInput();
        owner = _owner;
    }

    /*
    * @title NotOwner
    * @notice Error to check if the caller is the owner
    */
    error NotOwner();

    /*
    * @title NotProposedOwner
    * @notice Error to check if the caller is the proposed owner
    */
    error NotProposedOwner();

    /*
     * @title OwnershipTransferred
     * @notice Event to notify when ownership is transferred
     * @param previousOwner The previous owner
     * @param newOwner The new owner
     */
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /*
     * @title onlyOwner
     * @notice Modifier to check if the caller is the owner
     */
    modifier onlyOwner() {
        if (msg.sender != owner) revert NotOwner();
        _;
    }

    /*
     * @title onlyProposedOwner
     * @notice Modifier to check if the caller is the proposed owner
     */
    modifier onlyProposedOwner() {
        if (msg.sender != proposedOwner) revert NotProposedOwner();
        _;
    }

    /*
     * @title setProposedOwner
     * @notice Function to set the proposed owner
     * @param _proposedOwner The proposed owner
     */
    function setProposedOwner(address _proposedOwner) public onlyOwner {
        if (_proposedOwner == address(0)) revert InvalidInput();
        proposedOwner = _proposedOwner;
    }

    /*
     * @title acceptOwnership
     * @notice Function to accept the ownership
     */
    function acceptOwnership() public onlyProposedOwner {
        emit OwnershipTransferred(owner, proposedOwner);
        owner = proposedOwner;
        proposedOwner = address(0);
    }

    /*
     * @title cancelProposedOwnership
     * @notice Function to cancel the proposed ownership
     */
    function cancelProposedOwnership() public onlyOwner {
        proposedOwner = address(0);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

/*
 * @title IBETRStakingEventHandler
 * @notice Interface for the staking event handler
 */
interface IBETRStakingEventHandler {
    /*
     * @title onStakeChanged
     * @notice Function to handle the stake changed event
     * @param _user The user who changed the stake
     * @param _oldAmount The old amount of stake
     * @param _newAmount The new amount of stake
     */
    function onStakeChanged(address _user, uint256 _oldAmount, uint256 _newAmount) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/*
 * @title IBETRStakingStateProvider
 * @notice Interface for the staking state provider
 */
interface IBETRStakingStateProvider {
    /*
     * @title isRewarder
     * @notice Function to check if an address is a rewarder
     * @param _contract The address to check
     * @return isRewarder True if the address is a rewarder, false otherwise
     */
    function isRewarder(address _contract) external view returns (bool);

    /*
     * @title stakingToken
     * @notice Function to get the staking token
     * @return stakingToken The staking token
     */
    function stakingToken() external view returns (IERC20);
    
    /*
     * @title totalStakedAmount
     * @notice Function to get the total amount of tokens staked
     * @return totalStakedAmount The total amount of tokens staked
     */
    function totalStakedAmount() external view returns (uint256);

    /*
     * @title stakedAmount
     * @notice Function to get the amount of tokens staked by a user
     * @param _user The address of the user
     * @return stakedAmount The amount of tokens staked by the user
     */
    function stakedAmount(address _user) external view returns (uint256);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "evmVersion": "cancun",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_stakingContract","type":"address"},{"internalType":"address","name":"_rewardToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"NoClaimableReward","type":"error"},{"inputs":[],"name":"NoStakedAmount","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"NotProposedOwner","type":"error"},{"inputs":[],"name":"NotStakingContract","type":"error"},{"inputs":[],"name":"RewardingPaused","type":"error"},{"inputs":[],"name":"StakingContractNotRewarder","type":"error"},{"inputs":[],"name":"TokensTransferError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"RewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"_isRewardingPaused","type":"bool"}],"name":"RewardingPausedSet","type":"event"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"addReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_users","type":"address[]"}],"name":"batchClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelProposedOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"}],"name":"claimable","outputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimable","outputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRewardingPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_oldAmount","type":"uint256"},{"internalType":"uint256","name":"_newAmount","type":"uint256"}],"name":"onStakeChanged","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardAccumulatedPerStakedToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_proposedOwner","type":"address"}],"name":"setProposedOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isRewardingPaused","type":"bool"}],"name":"setRewardingPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingContract","outputs":[{"internalType":"contract IBETRStakingStateProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalRewardsClaimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalRewardsClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

608060405234801561000f575f5ffd5b50604051610fd0380380610fd083398101604081905261002e91610104565b826001600160a01b0381166100565760405163b4fa3fb360e01b815260040160405180910390fd5b5f80546001600160a01b0319166001600160a01b0392831617905582166100905760405163b4fa3fb360e01b815260040160405180910390fd5b6001600160a01b0381166100b75760405163b4fa3fb360e01b815260040160405180910390fd5b600480546001600160a01b039384166001600160a01b0319918216179091556005805492909316911617905550610144565b80516001600160a01b03811681146100ff575f5ffd5b919050565b5f5f5f60608486031215610116575f5ffd5b61011f846100e9565b925061012d602085016100e9565b915061013b604085016100e9565b90509250925092565b610e7f806101515f395ff3fe608060405234801561000f575f5ffd5b506004361061011c575f3560e01c80637d9e6ca1116100a9578063d153b60c1161006e578063d153b60c14610212578063d7c9d9b014610225578063ee99205c14610238578063f7c618c11461024b578063fb5f749f1461025e575f5ffd5b80637d9e6ca1146101c05780638da5cb5b146101c8578063a34b0f76146101f2578063aaf5eb68146101fb578063af38d7571461020a575f5ffd5b80634e71d92d116100ef5780634e71d92d146101775780635f7991391461017f57806374de4ec41461019c57806379ba5097146101af5780637ae0fb73146101b7575f5ffd5b80631f9eee2f1461012057806339670cc314610135578063402914f5146101515780634666d35b14610164575b5f5ffd5b61013361012e366004610c11565b610271565b005b61013e60065481565b6040519081526020015b60405180910390f35b61013e61015f366004610c4e565b6102d7565b610133610172366004610c4e565b6103ae565b610133610421565b60095461018c9060ff1681565b6040519015158152602001610148565b6101336101aa366004610c67565b6104bc565b61013361074e565b61013e60085481565b6101336107db565b5f546101da906001600160a01b031681565b6040516001600160a01b039091168152602001610148565b61013e60075481565b61013e670de0b6b3a764000081565b61013e610817565b6001546101da906001600160a01b031681565b610133610233366004610c7e565b610826565b6004546101da906001600160a01b031681565b6005546101da906001600160a01b031681565b61013361026c366004610cc2565b61093c565b5f546001600160a01b0316331461029b576040516330cd747160e01b815260040160405180910390fd5b6009805460ff19168215159081179091556040517f5fa26ba46a312195c8436849bd97aad3f7f345aa5b9a9052051c6a1cfe63da23905f90a250565b6004805460405163f993185560e01b81526001600160a01b03848116938201939093525f928392670de0b6b3a76400009291169063f993185590602401602060405180830381865afa15801561032f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103539190610d8d565b6006546103609190610db8565b61036a9190610dd5565b6001600160a01b0384165f908152600360209081526040808320546002909252822054929350909161039c9084610df4565b6103a69190610e07565b949350505050565b5f546001600160a01b031633146103d8576040516330cd747160e01b815260040160405180910390fd5b6001600160a01b0381166103ff5760405163b4fa3fb360e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60095460ff161561044557604051632802ad2160e01b815260040160405180910390fd5b6004805460405163f993185560e01b8152339281018390526104ba92916001600160a01b03169063f9931855906024015b602060405180830381865afa158015610491573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104b59190610d8d565b610a02565b565b60095460ff16156104e057604051632802ad2160e01b815260040160405180910390fd5b805f036105005760405163b4fa3fb360e01b815260040160405180910390fd5b60048054604051638e478cab60e01b815230928101929092526001600160a01b031690638e478cab90602401602060405180830381865afa158015610547573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061056b9190610e1a565b61058857604051632cc0f89760e21b815260040160405180910390fd5b5f60045f9054906101000a90046001600160a01b03166001600160a01b031663567e98f96040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105d9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105fd9190610d8d565b9050805f0361061f57604051631704edbb60e01b815260040160405180910390fd5b80610632670de0b6b3a764000084610db8565b61063c9190610dd5565b60065f82825461064c9190610e07565b925050819055508160085f8282546106649190610e07565b90915550506005546040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b03909116906323b872dd906064016020604051808303815f875af19250505080156106db575060408051601f3d908101601f191682019092526106d891810190610e1a565b60015b6106f857604051630389c7a160e51b815260040160405180910390fd5b8061071657604051630389c7a160e51b815260040160405180910390fd5b506040518281527fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d9060200160405180910390a15050565b6001546001600160a01b0316331461077957604051630f22ca5f60e01b815260040160405180910390fd5b6001545f80546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600180545f80546001600160a01b03199081166001600160a01b03841617909155169055565b5f546001600160a01b03163314610805576040516330cd747160e01b815260040160405180910390fd5b600180546001600160a01b0319169055565b5f610821336102d7565b905090565b6004546001600160a01b031633146108515760405163135420fb60e01b815260040160405180910390fd5b6001600160a01b0383166108785760405163b4fa3fb360e01b815260040160405180910390fd5b818114610937575f670de0b6b3a7640000836006546108979190610db8565b6108a19190610dd5565b6001600160a01b0385165f90815260036020908152604080832054600290925282205492935090916108d39084610df4565b6108dd9190610e07565b6001600160a01b0386165f908152600360205260409020819055600654909150670de0b6b3a764000090610912908590610db8565b61091c9190610dd5565b6001600160a01b0386165f9081526002602052604090205550505b505050565b5f546001600160a01b03163314610966576040516330cd747160e01b815260040160405180910390fd5b5f5b81518110156109fe576109f682828151811061098657610986610e35565b602002602001015160045f9054906101000a90046001600160a01b03166001600160a01b031663f99318558585815181106109c3576109c3610e35565b60200260200101516040518263ffffffff1660e01b815260040161047691906001600160a01b0391909116815260200190565b600101610968565b5050565b6001600160a01b038216610a295760405163b4fa3fb360e01b815260040160405180910390fd5b5f670de0b6b3a764000082600654610a419190610db8565b610a4b9190610dd5565b6001600160a01b0384165f9081526003602090815260408083205460029092528220549293509091610a7d9084610df4565b610a879190610e07565b9050805f03610ab85760405163e1ac865d60e01b81526001600160a01b038516600482015260240160405180910390fd5b6001600160a01b0384165f9081526002602090815260408083208590556003909152812081905560078054839290610af1908490610e07565b925050819055508060085f828254610b099190610df4565b909155505060055460405163a9059cbb60e01b81526001600160a01b038681166004830152602482018490529091169063a9059cbb906044016020604051808303815f875af1925050508015610b7c575060408051601f3d908101601f19168201909252610b7991810190610e1a565b60015b610b9957604051630389c7a160e51b815260040160405180910390fd5b80610bb757604051630389c7a160e51b815260040160405180910390fd5b50836001600160a01b03167f106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f724182604051610bf391815260200190565b60405180910390a250505050565b8015158114610c0e575f5ffd5b50565b5f60208284031215610c21575f5ffd5b8135610c2c81610c01565b9392505050565b80356001600160a01b0381168114610c49575f5ffd5b919050565b5f60208284031215610c5e575f5ffd5b610c2c82610c33565b5f60208284031215610c77575f5ffd5b5035919050565b5f5f5f60608486031215610c90575f5ffd5b610c9984610c33565b95602085013595506040909401359392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610cd2575f5ffd5b813567ffffffffffffffff811115610ce8575f5ffd5b8201601f81018413610cf8575f5ffd5b803567ffffffffffffffff811115610d1257610d12610cae565b8060051b604051601f19603f830116810181811067ffffffffffffffff82111715610d3f57610d3f610cae565b604052918252602081840181019290810187841115610d5c575f5ffd5b6020850194505b83851015610d8257610d7485610c33565b815260209485019401610d63565b509695505050505050565b5f60208284031215610d9d575f5ffd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610dcf57610dcf610da4565b92915050565b5f82610def57634e487b7160e01b5f52601260045260245ffd5b500490565b81810381811115610dcf57610dcf610da4565b80820180821115610dcf57610dcf610da4565b5f60208284031215610e2a575f5ffd5b8151610c2c81610c01565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220b0c8c4c08a35958f13bf415dc0f375c5648a43ac41b94d37031f0c293d8eacb764736f6c634300081c0033000000000000000000000000b0b492ac70aa250a067c5cc69ee9eb8af07f33c4000000000000000000000000808a12766632b456a74834f2fa8ae06dfc7482f1000000000000000000000000051024b653e8ec69e72693f776c41c2a9401fb07

Deployed Bytecode

0x608060405234801561000f575f5ffd5b506004361061011c575f3560e01c80637d9e6ca1116100a9578063d153b60c1161006e578063d153b60c14610212578063d7c9d9b014610225578063ee99205c14610238578063f7c618c11461024b578063fb5f749f1461025e575f5ffd5b80637d9e6ca1146101c05780638da5cb5b146101c8578063a34b0f76146101f2578063aaf5eb68146101fb578063af38d7571461020a575f5ffd5b80634e71d92d116100ef5780634e71d92d146101775780635f7991391461017f57806374de4ec41461019c57806379ba5097146101af5780637ae0fb73146101b7575f5ffd5b80631f9eee2f1461012057806339670cc314610135578063402914f5146101515780634666d35b14610164575b5f5ffd5b61013361012e366004610c11565b610271565b005b61013e60065481565b6040519081526020015b60405180910390f35b61013e61015f366004610c4e565b6102d7565b610133610172366004610c4e565b6103ae565b610133610421565b60095461018c9060ff1681565b6040519015158152602001610148565b6101336101aa366004610c67565b6104bc565b61013361074e565b61013e60085481565b6101336107db565b5f546101da906001600160a01b031681565b6040516001600160a01b039091168152602001610148565b61013e60075481565b61013e670de0b6b3a764000081565b61013e610817565b6001546101da906001600160a01b031681565b610133610233366004610c7e565b610826565b6004546101da906001600160a01b031681565b6005546101da906001600160a01b031681565b61013361026c366004610cc2565b61093c565b5f546001600160a01b0316331461029b576040516330cd747160e01b815260040160405180910390fd5b6009805460ff19168215159081179091556040517f5fa26ba46a312195c8436849bd97aad3f7f345aa5b9a9052051c6a1cfe63da23905f90a250565b6004805460405163f993185560e01b81526001600160a01b03848116938201939093525f928392670de0b6b3a76400009291169063f993185590602401602060405180830381865afa15801561032f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103539190610d8d565b6006546103609190610db8565b61036a9190610dd5565b6001600160a01b0384165f908152600360209081526040808320546002909252822054929350909161039c9084610df4565b6103a69190610e07565b949350505050565b5f546001600160a01b031633146103d8576040516330cd747160e01b815260040160405180910390fd5b6001600160a01b0381166103ff5760405163b4fa3fb360e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60095460ff161561044557604051632802ad2160e01b815260040160405180910390fd5b6004805460405163f993185560e01b8152339281018390526104ba92916001600160a01b03169063f9931855906024015b602060405180830381865afa158015610491573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104b59190610d8d565b610a02565b565b60095460ff16156104e057604051632802ad2160e01b815260040160405180910390fd5b805f036105005760405163b4fa3fb360e01b815260040160405180910390fd5b60048054604051638e478cab60e01b815230928101929092526001600160a01b031690638e478cab90602401602060405180830381865afa158015610547573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061056b9190610e1a565b61058857604051632cc0f89760e21b815260040160405180910390fd5b5f60045f9054906101000a90046001600160a01b03166001600160a01b031663567e98f96040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105d9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105fd9190610d8d565b9050805f0361061f57604051631704edbb60e01b815260040160405180910390fd5b80610632670de0b6b3a764000084610db8565b61063c9190610dd5565b60065f82825461064c9190610e07565b925050819055508160085f8282546106649190610e07565b90915550506005546040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b03909116906323b872dd906064016020604051808303815f875af19250505080156106db575060408051601f3d908101601f191682019092526106d891810190610e1a565b60015b6106f857604051630389c7a160e51b815260040160405180910390fd5b8061071657604051630389c7a160e51b815260040160405180910390fd5b506040518281527fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d9060200160405180910390a15050565b6001546001600160a01b0316331461077957604051630f22ca5f60e01b815260040160405180910390fd5b6001545f80546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600180545f80546001600160a01b03199081166001600160a01b03841617909155169055565b5f546001600160a01b03163314610805576040516330cd747160e01b815260040160405180910390fd5b600180546001600160a01b0319169055565b5f610821336102d7565b905090565b6004546001600160a01b031633146108515760405163135420fb60e01b815260040160405180910390fd5b6001600160a01b0383166108785760405163b4fa3fb360e01b815260040160405180910390fd5b818114610937575f670de0b6b3a7640000836006546108979190610db8565b6108a19190610dd5565b6001600160a01b0385165f90815260036020908152604080832054600290925282205492935090916108d39084610df4565b6108dd9190610e07565b6001600160a01b0386165f908152600360205260409020819055600654909150670de0b6b3a764000090610912908590610db8565b61091c9190610dd5565b6001600160a01b0386165f9081526002602052604090205550505b505050565b5f546001600160a01b03163314610966576040516330cd747160e01b815260040160405180910390fd5b5f5b81518110156109fe576109f682828151811061098657610986610e35565b602002602001015160045f9054906101000a90046001600160a01b03166001600160a01b031663f99318558585815181106109c3576109c3610e35565b60200260200101516040518263ffffffff1660e01b815260040161047691906001600160a01b0391909116815260200190565b600101610968565b5050565b6001600160a01b038216610a295760405163b4fa3fb360e01b815260040160405180910390fd5b5f670de0b6b3a764000082600654610a419190610db8565b610a4b9190610dd5565b6001600160a01b0384165f9081526003602090815260408083205460029092528220549293509091610a7d9084610df4565b610a879190610e07565b9050805f03610ab85760405163e1ac865d60e01b81526001600160a01b038516600482015260240160405180910390fd5b6001600160a01b0384165f9081526002602090815260408083208590556003909152812081905560078054839290610af1908490610e07565b925050819055508060085f828254610b099190610df4565b909155505060055460405163a9059cbb60e01b81526001600160a01b038681166004830152602482018490529091169063a9059cbb906044016020604051808303815f875af1925050508015610b7c575060408051601f3d908101601f19168201909252610b7991810190610e1a565b60015b610b9957604051630389c7a160e51b815260040160405180910390fd5b80610bb757604051630389c7a160e51b815260040160405180910390fd5b50836001600160a01b03167f106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f724182604051610bf391815260200190565b60405180910390a250505050565b8015158114610c0e575f5ffd5b50565b5f60208284031215610c21575f5ffd5b8135610c2c81610c01565b9392505050565b80356001600160a01b0381168114610c49575f5ffd5b919050565b5f60208284031215610c5e575f5ffd5b610c2c82610c33565b5f60208284031215610c77575f5ffd5b5035919050565b5f5f5f60608486031215610c90575f5ffd5b610c9984610c33565b95602085013595506040909401359392505050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215610cd2575f5ffd5b813567ffffffffffffffff811115610ce8575f5ffd5b8201601f81018413610cf8575f5ffd5b803567ffffffffffffffff811115610d1257610d12610cae565b8060051b604051601f19603f830116810181811067ffffffffffffffff82111715610d3f57610d3f610cae565b604052918252602081840181019290810187841115610d5c575f5ffd5b6020850194505b83851015610d8257610d7485610c33565b815260209485019401610d63565b509695505050505050565b5f60208284031215610d9d575f5ffd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610dcf57610dcf610da4565b92915050565b5f82610def57634e487b7160e01b5f52601260045260245ffd5b500490565b81810381811115610dcf57610dcf610da4565b80820180821115610dcf57610dcf610da4565b5f60208284031215610e2a575f5ffd5b8151610c2c81610c01565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220b0c8c4c08a35958f13bf415dc0f375c5648a43ac41b94d37031f0c293d8eacb764736f6c634300081c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000b0b492ac70aa250a067c5cc69ee9eb8af07f33c4000000000000000000000000808a12766632b456a74834f2fa8ae06dfc7482f1000000000000000000000000051024b653e8ec69e72693f776c41c2a9401fb07

-----Decoded View---------------
Arg [0] : _owner (address): 0xb0b492Ac70AA250A067c5Cc69eE9eb8AF07f33C4
Arg [1] : _stakingContract (address): 0x808a12766632b456a74834F2FA8aE06DFC7482f1
Arg [2] : _rewardToken (address): 0x051024B653E8ec69E72693F776c41C2A9401FB07

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000b0b492ac70aa250a067c5cc69ee9eb8af07f33c4
Arg [1] : 000000000000000000000000808a12766632b456a74834f2fa8ae06dfc7482f1
Arg [2] : 000000000000000000000000051024b653e8ec69e72693f776c41c2a9401fb07


Deployed Bytecode Sourcemap

557:7270:1:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6871:178;;;;;;:::i;:::-;;:::i;:::-;;852:46;;;;;;;;;529:25:7;;;517:2;502:18;852:46:1;;;;;;;;4467:321;;;;;;:::i;:::-;;:::i;1656:179:3:-;;;;;;:::i;:::-;;:::i;6053:158:1:-;;;:::i;986:29::-;;;;;;;;;;;;1099:14:7;;1092:22;1074:41;;1062:2;1047:18;986:29:1;934:187:7;5196:774:1;;;;;;:::i;:::-;;:::i;1934:183:3:-;;;:::i;944:36:1:-;;;;;;2233:95:3;;;:::i;267:20::-;;;;;-1:-1:-1;;;;;267:20:3;;;;;;-1:-1:-1;;;;;1521:32:7;;;1503:51;;1491:2;1476:18;267:20:3;1357:203:7;904:34:1;;;;;;720:40;;756:4;720:40;;4960:104;;;:::i;293:28:3:-;;;;;-1:-1:-1;;;;;293:28:3;;;7307:518:1;;;;;;:::i;:::-;;:::i;767:48::-;;;;;-1:-1:-1;;;;;767:48:1;;;821:25;;;;;-1:-1:-1;;;;;821:25:1;;;6494:205;;;;;;:::i;:::-;;:::i;6871:178::-;1227:5:3;;-1:-1:-1;;;;;1227:5:3;1213:10;:19;1209:42;;1241:10;;-1:-1:-1;;;1241:10:3;;;;;;;;;;;1209:42;6951:17:1::1;:38:::0;;-1:-1:-1;;6951:38:1::1;::::0;::::1;;::::0;;::::1;::::0;;;7004::::1;::::0;::::1;::::0;-1:-1:-1;;7004:38:1::1;6871:178:::0;:::o;4467:321::-;4608:15;;;:37;;-1:-1:-1;;;4608:37:1;;-1:-1:-1;;;;;1521:32:7;;;4608:37:1;;;1503:51:7;;;;4524:15:1;;;;756:4;;4608:15;;;:28;;1476:18:7;;4608:37:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4574:31;;:71;;;;:::i;:::-;:83;;;;:::i;:::-;-1:-1:-1;;;;;4729:17:1;;4667:26;4729:17;;;:8;:17;;;;;;;;;4711:6;:15;;;;;;4551:106;;-1:-1:-1;4667:26:1;;4696:30;;4551:106;4696:30;:::i;:::-;:50;;;;:::i;:::-;4667:79;4467:321;-1:-1:-1;;;;4467:321:1:o;1656:179:3:-;1227:5;;-1:-1:-1;;;;;1227:5:3;1213:10;:19;1209:42;;1241:10;;-1:-1:-1;;;1241:10:3;;;;;;;;;;;1209:42;-1:-1:-1;;;;;1737:28:3;::::1;1733:55;;1774:14;;-1:-1:-1::0;;;1774:14:3::1;;;;;;;;;;;1733:55;1798:13;:30:::0;;-1:-1:-1;;;;;;1798:30:3::1;-1:-1:-1::0;;;;;1798:30:3;;;::::1;::::0;;;::::1;::::0;;1656:179::o;6053:158:1:-;6091:17;;;;6087:47;;;6117:17;;-1:-1:-1;;;6117:17:1;;;;;;;;;;;6087:47;6163:15;;;:40;;-1:-1:-1;;;6163:40:1;;6151:10;6163:40;;;1503:51:7;;;6144:60:1;;6151:10;-1:-1:-1;;;;;6163:15:1;;:28;;1476:18:7;;6163:40:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6144:6;:60::i;:::-;6053:158::o;5196:774::-;5253:17;;;;5249:47;;;5279:17;;-1:-1:-1;;;5279:17:1;;;;;;;;;;;5249:47;5310:7;5321:1;5310:12;5306:39;;5331:14;;-1:-1:-1;;;5331:14:1;;;;;;;;;;;5306:39;5360:15;;;:41;;-1:-1:-1;;;5360:41:1;;5395:4;5360:41;;;1503:51:7;;;;-1:-1:-1;;;;;5360:15:1;;:26;;1476:18:7;;5360:41:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5355:83;;5410:28;;-1:-1:-1;;;5410:28:1;;;;;;;;;;;5355:83;5449:25;5477:15;;;;;;;;;-1:-1:-1;;;;;5477:15:1;-1:-1:-1;;;;;5477:33:1;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5449:63;;5526:17;5547:1;5526:22;5522:51;;5557:16;;-1:-1:-1;;;5557:16:1;;;;;;;;;;;5522:51;5643:17;5620:19;756:4;5620:7;:19;:::i;:::-;5619:41;;;;:::i;:::-;5584:31;;:76;;;;;;;:::i;:::-;;;;;;;;5695:7;5670:21;;:32;;;;;;;:::i;:::-;;;;-1:-1:-1;;5717:11:1;;:60;;-1:-1:-1;;;5717:60:1;;5742:10;5717:60;;;5148:51:7;5762:4:1;5215:18:7;;;5208:60;5284:18;;;5277:34;;;-1:-1:-1;;;;;5717:11:1;;;;:24;;5121:18:7;;5717:60:1;;;;;;;;;;;;;;;;;;;-1:-1:-1;5717:60:1;;;;;;;;-1:-1:-1;;5717:60:1;;;;;;;;;;;;:::i;:::-;;;5713:215;;5896:21;;-1:-1:-1;;;5896:21:1;;;;;;;;;;;5713:215;5820:7;5815:42;;5836:21;;-1:-1:-1;;;5836:21:1;;;;;;;;;;;5815:42;-1:-1:-1;5943:20:1;;529:25:7;;;5943:20:1;;517:2:7;502:18;5943:20:1;;;;;;;5239:731;5196:774;:::o;1934:183:3:-;1448:13;;-1:-1:-1;;;;;1448:13:3;1434:10;:27;1430:58;;1470:18;;-1:-1:-1;;;1470:18:3;;;;;;;;;;;1430:58;2029:13:::1;::::0;::::1;2022:5:::0;;2001:42:::1;::::0;-1:-1:-1;;;;;2029:13:3;;::::1;::::0;2022:5;;::::1;::::0;2001:42:::1;::::0;::::1;2061:13;::::0;;::::1;2053:21:::0;;-1:-1:-1;;;;;;2053:21:3;;::::1;-1:-1:-1::0;;;;;2061:13:3;::::1;2053:21;::::0;;;2084:26:::1;::::0;;1934:183::o;2233:95::-;1227:5;;-1:-1:-1;;;;;1227:5:3;1213:10;:19;1209:42;;1241:10;;-1:-1:-1;;;1241:10:3;;;;;;;;;;;1209:42;2295:13:::1;:26:::0;;-1:-1:-1;;;;;;2295:26:3::1;::::0;;2233:95::o;4960:104:1:-;5002:15;5036:21;5046:10;5036:9;:21::i;:::-;5029:28;;4960:104;:::o;7307:518::-;3236:15;;-1:-1:-1;;;;;3236:15:1;3214:10;:38;3210:71;;3261:20;;-1:-1:-1;;;3261:20:1;;;;;;;;;;;3210:71;-1:-1:-1;;;;;7427:19:1;::::1;7423:46;;7455:14;;-1:-1:-1::0;;;7455:14:1::1;;;;;;;;;;;7423:46;7479:37:::0;;;7509:7:::1;7479:37;7526:20;756:4;7583:10;7549:31;;:44;;;;:::i;:::-;:56;;;;:::i;:::-;-1:-1:-1::0;;;;;7675:15:1;::::1;7615:26;7675:15:::0;;;:8:::1;:15;::::0;;;;;;;;7659:6:::1;:13:::0;;;;;;7526:79;;-1:-1:-1;7615:26:1;;7644:28:::1;::::0;7526:79;7644:28:::1;:::i;:::-;:46;;;;:::i;:::-;-1:-1:-1::0;;;;;7700:15:1;::::1;;::::0;;;:8:::1;:15;::::0;;;;:36;;;7762:31:::1;::::0;7615:75;;-1:-1:-1;756:4:1::1;::::0;7762:44:::1;::::0;7796:10;;7762:44:::1;:::i;:::-;:56;;;;:::i;:::-;-1:-1:-1::0;;;;;7746:13:1;::::1;;::::0;;;:6:::1;:13;::::0;;;;:72;-1:-1:-1;;3291:1:1::1;7307:518:::0;;;:::o;6494:205::-;1227:5:3;;-1:-1:-1;;;;;1227:5:3;1213:10;:19;1209:42;;1241:10;;-1:-1:-1;;;1241:10:3;;;;;;;;;;;1209:42;6571:9:1::1;6566:127;6590:6;:13;6586:1;:17;6566:127;;;6624:58;6631:6;6638:1;6631:9;;;;;;;;:::i;:::-;;;;;;;6642:15;;;;;;;;;-1:-1:-1::0;;;;;6642:15:1::1;-1:-1:-1::0;;;;;6642:28:1::1;;6671:6;6678:1;6671:9;;;;;;;;:::i;:::-;;;;;;;6642:39;;;;;;;;;;;;;;-1:-1:-1::0;;;;;1521:32:7;;;;1503:51;;1491:2;1476:18;;1357:203;6624:58:1::1;6605:3;;6566:127;;;;6494:205:::0;:::o;3427:822::-;-1:-1:-1;;;;;3504:19:1;;3500:46;;3532:14;;-1:-1:-1;;;3532:14:1;;;;;;;;;;;3500:46;3557:20;756:4;3614:13;3580:31;;:47;;;;:::i;:::-;:59;;;;:::i;:::-;-1:-1:-1;;;;;3709:15:1;;3649:26;3709:15;;;:8;:15;;;;;;;;;3693:6;:13;;;;;;3557:82;;-1:-1:-1;3649:26:1;;3678:28;;3557:82;3678:28;:::i;:::-;:46;;;;:::i;:::-;3649:75;;3738:18;3760:1;3738:23;3734:60;;3770:24;;-1:-1:-1;;;3770:24:1;;-1:-1:-1;;;;;1521:32:7;;3770:24:1;;;1503:51:7;1476:18;;3770:24:1;;;;;;;3734:60;-1:-1:-1;;;;;3805:13:1;;;;;;:6;:13;;;;;;;;:28;;;3843:8;:15;;;;;:19;;;3872;:41;;3895:18;;3805:13;3872:41;;3895:18;;3872:41;:::i;:::-;;;;;;;;3948:18;3923:21;;:43;;;;;;;:::i;:::-;;;;-1:-1:-1;;3981:11:1;;:47;;-1:-1:-1;;;3981:47:1;;-1:-1:-1;;;;;5646:32:7;;;3981:47:1;;;5628:51:7;5695:18;;;5688:34;;;3981:11:1;;;;:20;;5601:18:7;;3981:47:1;;;;;;;;;;;;;;;;;;;-1:-1:-1;3981:47:1;;;;;;;;-1:-1:-1;;3981:47:1;;;;;;;;;;;;:::i;:::-;;;3977:202;;4147:21;;-1:-1:-1;;;4147:21:1;;;;;;;;;;;3977:202;4071:7;4066:42;;4087:21;;-1:-1:-1;;;4087:21:1;;;;;;;;;;;4066:42;4029:90;4216:5;-1:-1:-1;;;;;4202:40:1;;4223:18;4202:40;;;;529:25:7;;517:2;502:18;;383:177;4202:40:1;;;;;;;;3490:759;;3427:822;;:::o;14:118:7:-;100:5;93:13;86:21;79:5;76:32;66:60;;122:1;119;112:12;66:60;14:118;:::o;137:241::-;193:6;246:2;234:9;225:7;221:23;217:32;214:52;;;262:1;259;252:12;214:52;301:9;288:23;320:28;342:5;320:28;:::i;:::-;367:5;137:241;-1:-1:-1;;;137:241:7:o;565:173::-;633:20;;-1:-1:-1;;;;;682:31:7;;672:42;;662:70;;728:1;725;718:12;662:70;565:173;;;:::o;743:186::-;802:6;855:2;843:9;834:7;830:23;826:32;823:52;;;871:1;868;861:12;823:52;894:29;913:9;894:29;:::i;1126:226::-;1185:6;1238:2;1226:9;1217:7;1213:23;1209:32;1206:52;;;1254:1;1251;1244:12;1206:52;-1:-1:-1;1299:23:7;;1126:226;-1:-1:-1;1126:226:7:o;1565:420::-;1642:6;1650;1658;1711:2;1699:9;1690:7;1686:23;1682:32;1679:52;;;1727:1;1724;1717:12;1679:52;1750:29;1769:9;1750:29;:::i;:::-;1740:39;1848:2;1833:18;;1820:32;;-1:-1:-1;1949:2:7;1934:18;;;1921:32;;1565:420;-1:-1:-1;;;1565:420:7:o;2453:127::-;2514:10;2509:3;2505:20;2502:1;2495:31;2545:4;2542:1;2535:15;2569:4;2566:1;2559:15;2585:1127;2669:6;2722:2;2710:9;2701:7;2697:23;2693:32;2690:52;;;2738:1;2735;2728:12;2690:52;2778:9;2765:23;2811:18;2803:6;2800:30;2797:50;;;2843:1;2840;2833:12;2797:50;2866:22;;2919:4;2911:13;;2907:27;-1:-1:-1;2897:55:7;;2948:1;2945;2938:12;2897:55;2988:2;2975:16;3014:18;3006:6;3003:30;3000:56;;;3036:18;;:::i;:::-;3082:6;3079:1;3075:14;3118:2;3112:9;3181:2;3177:7;3172:2;3168;3164:11;3160:25;3152:6;3148:38;3252:6;3240:10;3237:22;3216:18;3204:10;3201:34;3198:62;3195:88;;;3263:18;;:::i;:::-;3299:2;3292:22;3349;;;3399:2;3429:11;;;3425:20;;;3349:22;3387:15;;3457:19;;;3454:39;;;3489:1;3486;3479:12;3454:39;3521:2;3517;3513:11;3502:22;;3533:148;3549:6;3544:3;3541:15;3533:148;;;3615:23;3634:3;3615:23;:::i;:::-;3603:36;;3668:2;3566:12;;;;3659;3533:148;;;-1:-1:-1;3700:6:7;2585:1127;-1:-1:-1;;;;;;2585:1127:7:o;3717:184::-;3787:6;3840:2;3828:9;3819:7;3815:23;3811:32;3808:52;;;3856:1;3853;3846:12;3808:52;-1:-1:-1;3879:16:7;;3717:184;-1:-1:-1;3717:184:7:o;3906:127::-;3967:10;3962:3;3958:20;3955:1;3948:31;3998:4;3995:1;3988:15;4022:4;4019:1;4012:15;4038:168;4111:9;;;4142;;4159:15;;;4153:22;;4139:37;4129:71;;4180:18;;:::i;:::-;4038:168;;;;:::o;4211:217::-;4251:1;4277;4267:132;;4321:10;4316:3;4312:20;4309:1;4302:31;4356:4;4353:1;4346:15;4384:4;4381:1;4374:15;4267:132;-1:-1:-1;4413:9:7;;4211:217::o;4433:128::-;4500:9;;;4521:11;;;4518:37;;;4535:18;;:::i;4566:125::-;4631:9;;;4652:10;;;4649:36;;;4665:18;;:::i;4696:245::-;4763:6;4816:2;4804:9;4795:7;4791:23;4787:32;4784:52;;;4832:1;4829;4822:12;4784:52;4864:9;4858:16;4883:28;4905:5;4883:28;:::i;5322:127::-;5383:10;5378:3;5374:20;5371:1;5364:31;5414:4;5411:1;5404:15;5438:4;5435:1;5428:15

Swarm Source

ipfs://b0c8c4c08a35958f13bf415dc0f375c5648a43ac41b94d37031f0c293d8eacb7

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.