Source Code
Overview
S Balance
0 S
More Info
ContractCreator
Loading...
Loading
Contract Name:
MasterChefRewarder
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 800 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; import {IMasterChefRewarder} from "../interfaces/IMasterChefRewarder.sol"; import {IMasterChef} from "../interfaces/IMasterChef.sol"; import {BaseRewarder, IBaseRewarder} from "./BaseRewarder.sol"; import {Rewarder} from "../libraries/Rewarder.sol"; /** * @title MasterChef Rewarder Contract * @dev Contract for distributing rewards to stakers in the MasterChef contract. */ contract MasterChefRewarder is BaseRewarder, IMasterChefRewarder { using Rewarder for Rewarder.Parameter; Status internal _status; /** * @dev Constructor for MasterChefRewarder contract. * @param caller The address of the contract that will call the onModify function. */ constructor(address caller) BaseRewarder(caller) {} /** * @dev Links the rewarder to the MasterChef contract. * Can only be called by the caller contract and only once. * @param pid The pool ID of the staking pool. */ function link(uint256 pid) public override { if (msg.sender != _caller) revert BaseRewarder__InvalidCaller(); if (_status != Status.Unlinked) revert MasterChefRewarder__AlreadyLinked(); if (pid != _pid()) revert BaseRewarder__InvalidPid(pid); if (_isStopped) revert BaseRewarder__Stopped(); _status = Status.Linked; } /** * @dev Unlinks the rewarder from the MasterChef contract. * Can only be called by the caller contract and only once. * @param pid The pool ID of the staking pool. */ function unlink(uint256 pid) public override { if (msg.sender != _caller) revert BaseRewarder__InvalidCaller(); if (pid != _pid()) revert BaseRewarder__InvalidPid(pid); if (_status != Status.Linked) revert MasterChefRewarder__NotLinked(); _status = Status.Stopped; _isStopped = true; } /** * @dev Reverts as the MasterChefRewarder contract should be stopped by the unlink function. */ function stop() public pure override(IBaseRewarder, BaseRewarder) { revert MasterChefRewarder__UseUnlink(); } /** * @dev Called by the caller contract to update the rewards for a given account. * If the rewarder is not linked, the function will revert. * @param account The account to update rewards for. * @param pid The pool ID of the staking pool. * @param oldBalance The old balance of the account. * @param newBalance The new balance of the account. * @param oldTotalSupply The old total supply of the staking pool. * @return reward The amount of rewards sent to the account. */ function onModify(address account, uint256 pid, uint256 oldBalance, uint256 newBalance, uint256 oldTotalSupply) public override(BaseRewarder, IBaseRewarder) returns (uint256 reward) { if (_status != Status.Linked) revert MasterChefRewarder__NotLinked(); reward = BaseRewarder.onModify(account, pid, oldBalance, newBalance, oldTotalSupply); _claim(account, reward); } /** * @dev Called by the caller contract to update the rewards for a given account in an emergency. * If the rewarder is not linked, the function will revert. * @param account account to update rewards for * @param pid The pool ID of the staking pool * @param oldBalance The old balance of the account. * @param newBalance The new balance of the account. * @param oldTotalSupply The old total supply of the staking pool. */ function onEmergency(address account, uint256 pid, uint256 oldBalance, uint256 newBalance, uint256 oldTotalSupply) public { if (_status != Status.Linked) revert MasterChefRewarder__NotLinked(); if (msg.sender != _caller) revert BaseRewarder__InvalidCaller(); if (pid != _pid()) revert BaseRewarder__InvalidPid(pid); uint256 totalRewards = oldTotalSupply == 0 ? 0 : _rewarder.getTotalRewards(_rewardsPerSecond, _endTimestamp, oldTotalSupply); uint256 rewards = _rewarder.update(account, oldBalance, newBalance, oldTotalSupply, totalRewards); // redistribute rewards _totalUnclaimedRewards = _totalUnclaimedRewards + totalRewards; _rewarder.updateAccDebtPerShare(_getTotalSupply(), rewards); } /** * @dev Returns the total supply of the staking pool. * @return The total supply of the staking pool. */ function _getTotalSupply() internal view override returns (uint256) { return _status != Status.Linked ? 0 : IMasterChef(_caller).getTotalDeposit(_pid()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ 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.0; import {IBaseRewarder} from "./IBaseRewarder.sol"; interface IMasterChefRewarder is IBaseRewarder { error MasterChefRewarder__AlreadyLinked(); error MasterChefRewarder__NotLinked(); error MasterChefRewarder__UseUnlink(); enum Status { Unlinked, Linked, Stopped } function link(uint256 pid) external; function unlink(uint256 pid) external; function onEmergency(address account, uint256 pid, uint256 oldBalance, uint256 newBalance, uint256 oldTotalSupply) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; import {IMasterChefRewarder} from "./IMasterChefRewarder.sol"; import {IMetro} from "./IMetro.sol"; import {IVoter} from "./IVoter.sol"; import {Rewarder} from "../libraries/Rewarder.sol"; import {Amounts} from "../libraries/Amounts.sol"; import {IRewarderFactory} from "./IRewarderFactory.sol"; interface IMasterChef { error MasterChef__InvalidShares(); error MasterChef__InvalidMetroPerSecond(); error MasterChef__ZeroAddress(); error MasterChef__NotMasterchefRewarder(); error MasterChef__CannotRenounceOwnership(); error MasterChef__MintFailed(); error MasterChef__TrusteeNotSet(); error MasterChef__NotTrustedCaller(); struct Farm { Amounts.Parameter amounts; Rewarder.Parameter rewarder; IERC20 token; IMasterChefRewarder extraRewarder; } // bool depositOnBehalf; // true if v2 pool zap in should be possible // uint256 startTime; event PositionModified(uint256 indexed pid, address indexed account, int256 deltaAmount, uint256 metroReward); event MetroPerSecondSet(uint256 metroPerSecond); event FarmAdded(uint256 indexed pid, IERC20 indexed token); event ExtraRewarderSet(uint256 indexed pid, IMasterChefRewarder extraRewarder); event TreasurySet(address indexed treasury); event VoterSet(IVoter indexed newVoter); event TrusteeSet(address indexed trustee); event MintMetroSet(bool mintMetro); event OperatorUpdated(address indexed operator); function add(IERC20 token, IMasterChefRewarder extraRewarder) external; function claim(uint256[] memory pids) external; function deposit(uint256 pid, uint256 amount) external; function depositOnBehalf(uint256 pid, uint256 amount, address account) external; function emergencyWithdraw(uint256 pid) external; function getDeposit(uint256 pid, address account) external view returns (uint256); function getLastUpdateTimestamp(uint256 pid) external view returns (uint256); function getPendingRewards(address account, uint256[] memory pids) external view returns (uint256[] memory metroRewards, IERC20[] memory extraTokens, uint256[] memory extraRewards); function getExtraRewarder(uint256 pid) external view returns (IMasterChefRewarder); function getMetro() external view returns (IMetro); function getMetroPerSecond() external view returns (uint256); function getMetroPerSecondForPid(uint256 pid) external view returns (uint256); function getNumberOfFarms() external view returns (uint256); function getToken(uint256 pid) external view returns (IERC20); function getTotalDeposit(uint256 pid) external view returns (uint256); function getTreasury() external view returns (address); function getTreasuryShare() external view returns (uint256); function getRewarderFactory() external view returns (IRewarderFactory); function getLBHooksManager() external view returns (address); function getVoter() external view returns (IVoter); function setExtraRewarder(uint256 pid, IMasterChefRewarder extraRewarder) external; function setMetroPerSecond(uint96 metroPerSecond) external; function setTreasury(address treasury) external; function setVoter(IVoter voter) external; function setTrustee(address trustee) external; function updateAll(uint256[] calldata pids) external; function withdraw(uint256 pid, uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {Ownable2StepUpgradeable} from "openzeppelin-contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import {SafeERC20, IERC20} from "openzeppelin/token/ERC20/utils/SafeERC20.sol"; import {Clone} from "../libraries/Clone.sol"; import {Rewarder} from "../libraries/Rewarder.sol"; import {IBaseRewarder} from "../interfaces/IBaseRewarder.sol"; /** * @title Base Rewarder Contract * @dev Base contract for reward distribution to stakers. */ abstract contract BaseRewarder is Ownable2StepUpgradeable, Clone, IBaseRewarder { using SafeERC20 for IERC20; using Rewarder for Rewarder.Parameter; address public immutable implementation; address internal immutable _caller; uint256 internal _rewardsPerSecond; uint256 internal _totalUnclaimedRewards; uint256 internal _reserve; uint256 internal _endTimestamp; bool internal _isStopped; Rewarder.Parameter internal _rewarder; /** * @dev Constructor for BaseRewarder contract. * @param caller The address of the contract that will call the onModify function. */ constructor(address caller) { _caller = caller; implementation = address(this); _disableInitializers(); } /** * @dev Initializes the BaseRewarder contract. * @param initialOwner The initial owner of the contract. */ function initialize(address initialOwner) public virtual override initializer { __Ownable_init(initialOwner); } /** * @dev Allows the contract to receive native tokens only if the token is address(0). */ receive() external payable { _nativeReceived(); } /** * @dev Allows the contract to receive native tokens only if the token is address(0). */ fallback() external payable { _nativeReceived(); } /** * @dev Returns the address of the token to be distributed as rewards. * @return The address of the token to be distributed as rewards. */ function getToken() public view virtual override returns (IERC20) { return _token(); } /** * @dev Returns the address of the contract that calls the onModify function. * @return The address of the caller contract. */ function getCaller() public view virtual override returns (address) { return _caller; } /** * @dev Returns the pool ID of the staking pool. * @return The pool ID. */ function getPid() public view virtual override returns (uint256) { return _pid(); } /** * @dev Returns the rewarder parameter values. * @return token The token to be distributed as rewards. * @return rewardPerSecond The reward per second. * @return lastUpdateTimestamp The last update timestamp. * @return endTimestamp The end timestamp. */ function getRewarderParameter() public view virtual override returns (IERC20 token, uint256 rewardPerSecond, uint256 lastUpdateTimestamp, uint256 endTimestamp) { return (_token(), _rewardsPerSecond, _rewarder.lastUpdateTimestamp, _endTimestamp); } /** * @dev Returns the remaining reward. * @return The remaining reward. */ function getRemainingReward() public view virtual override returns (uint256) { uint256 totalSupply = _getTotalSupply(); uint256 totalRewards = _rewarder.getTotalRewards(_rewardsPerSecond, _endTimestamp, totalSupply); uint256 totalUnclaimedRewards = _totalUnclaimedRewards + totalRewards; return _balanceOfThis(_token()) - totalUnclaimedRewards; } /** * @dev Returns the pending rewards for a given account. * @param account The account to check for pending rewards. * @param balance The balance of the account. * @param totalSupply The total supply of the staking pool. * @return The token and the amount of pending rewards. */ function getPendingReward(address account, uint256 balance, uint256 totalSupply) public view virtual override returns (IERC20, uint256) { uint256 totalRewards = _rewarder.getTotalRewards(_rewardsPerSecond, _endTimestamp, totalSupply); return (_token(), _rewarder.getPendingReward(account, balance, totalSupply, totalRewards)); } /** * @dev Returns whether the reward distribution has been stopped. * @return True if the reward distribution has been stopped, false otherwise. */ function isStopped() public view virtual override returns (bool) { return _isStopped; } /** * @dev Sets the start of the reward distribution. * @param maxRewardPerSecond The maximum reward per second. * @param startTimestamp The start timestamp. * @param expectedDuration The expected duration of the reward distribution. * @return rewardPerSecond The actual reward per second. */ function setRewarderParameters(uint256 maxRewardPerSecond, uint256 startTimestamp, uint256 expectedDuration) public virtual override onlyOwner returns (uint256 rewardPerSecond) { return _setRewardParameters(maxRewardPerSecond, startTimestamp, expectedDuration); } /** * @dev Sets the reward per second and expected duration. * If the expected duration is 0, the reward distribution will be stopped. * @param maxRewardPerSecond The maximum reward per second. * @param expectedDuration The expected duration of the reward distribution. * @return rewardPerSecond The actual reward per second. */ function setRewardPerSecond(uint256 maxRewardPerSecond, uint256 expectedDuration) public virtual override onlyOwner returns (uint256 rewardPerSecond) { uint256 lastUpdateTimestamp = _rewarder.lastUpdateTimestamp; uint256 startTimestamp = lastUpdateTimestamp > block.timestamp ? lastUpdateTimestamp : block.timestamp; return _setRewardParameters(maxRewardPerSecond, startTimestamp, expectedDuration); } /** * @dev Stops the reward distribution. */ function stop() public virtual override onlyOwner { if (_isStopped) revert BaseRewarder__AlreadyStopped(); uint256 totalSupply = _getTotalSupply(); uint256 totalPendingRewards = _rewarder.getTotalRewards(_rewardsPerSecond, _endTimestamp, totalSupply); _totalUnclaimedRewards += totalPendingRewards; _rewarder.updateAccDebtPerShare(totalSupply, totalPendingRewards); _setRewardParameters(0, block.timestamp, 0); _isStopped = true; emit Stopped(); } /** * @dev Transfers any remaining tokens to the specified account. * If the token is the reward token, only the excess amount will be transferred. * Even if the rewarder is stopped, the unclaimed rewards will not be transferred; unless the total supply is 0. * (for example if there is leftover because of emergency withdrawal or roundings). * @param token The token to transfer. * @param account The account to transfer the tokens to. */ function sweep(IERC20 token, address account) public virtual override onlyOwner { uint256 balance = _balanceOfThis(token); if (token == _token()) { if (_isStopped) { if (_getTotalSupply() > 0) balance -= _totalUnclaimedRewards; } else { balance -= _reserve; } } if (balance == 0) revert BaseRewarder__ZeroAmount(); _safeTransferTo(token, account, balance); emit Swept(token, account, balance); } /** * @dev Called by the caller contract to update the rewards for a given account. * @param account The account to update rewards for. * @param pid The pool ID of the staking pool. * @param oldBalance The old balance of the account. * @param newBalance The new balance of the account. * @param oldTotalSupply The old total supply of the staking pool. */ function onModify(address account, uint256 pid, uint256 oldBalance, uint256 newBalance, uint256 oldTotalSupply) public virtual override returns (uint256) { if (msg.sender != _caller) revert BaseRewarder__InvalidCaller(); if (pid != _pid()) revert BaseRewarder__InvalidPid(pid); return _update(account, oldBalance, newBalance, oldTotalSupply); } /** * @dev Blocks the renouncing of ownership. */ function renounceOwnership() public pure override { revert BaseRewarder__CannotRenounceOwnership(); } /** * @dev Returns the address of the token to be distributed as rewards. * @return The address of the token to be distributed as rewards. */ function _token() internal pure virtual returns (IERC20) { return IERC20(_getArgAddress(0)); } /** * @dev Returns the pool ID of the staking pool. * @return The pool ID. */ function _pid() internal pure virtual returns (uint256) { return _getArgUint256(20); } /** * @dev Returns the balance of the specified token held by the contract. * @param token The token to check the balance of. * @return The balance of the token held by the contract. */ function _balanceOfThis(IERC20 token) internal view virtual returns (uint256) { return address(token) == address(0) ? address(this).balance : token.balanceOf(address(this)); } /** * @dev Updates a given account and returns the rewards. * @param account The account to claim rewards for. * @param oldBalance The old balance of the account. * @param newBalance The new balance of the account. * @param oldTotalSupply The old total supply of the staking pool. * @return rewards The rewards of the account. */ function _update(address account, uint256 oldBalance, uint256 newBalance, uint256 oldTotalSupply) internal virtual returns (uint256 rewards) { uint256 totalUnclaimedRewards = _totalUnclaimedRewards; uint256 reserve = _reserve; uint256 totalRewards = oldTotalSupply == 0 ? 0 : _rewarder.getTotalRewards(_rewardsPerSecond, _endTimestamp, oldTotalSupply); rewards = _rewarder.update(account, oldBalance, newBalance, oldTotalSupply, totalRewards); _totalUnclaimedRewards = totalUnclaimedRewards + totalRewards - rewards; _reserve = reserve - rewards; } /** * @dev Claims tokens to the specified account. * @param account The account to claim rewards for. * @param amount The amount of tokens to claim. */ function _claim(address account, uint256 amount) internal virtual { IERC20 token = _token(); _safeTransferTo(token, account, amount); emit Claim(account, token, amount); } /** * @dev Safely transfers the specified amount of tokens to the specified account. * @param token The token to transfer. * @param account The account to transfer the tokens to. * @param amount The amount of tokens to transfer. */ function _safeTransferTo(IERC20 token, address account, uint256 amount) internal virtual { if (amount == 0) return; if (address(token) == address(0)) { (bool s,) = account.call{value: amount}(""); if (!s) revert BaseRewarder__NativeTransferFailed(); } else { token.safeTransfer(account, amount); } } /** * @dev Sets the reward parameters. * This will set the reward per second, the start timestamp, and the end timestamp. * If the expected duration is 0, the reward distribution will be stopped. * @param maxRewardPerSecond The maximum reward per second. * @param startTimestamp The start timestamp. * @param expectedDuration The expected duration of the reward distribution. * @return rewardPerSecond The actual reward per second. */ function _setRewardParameters(uint256 maxRewardPerSecond, uint256 startTimestamp, uint256 expectedDuration) internal virtual returns (uint256 rewardPerSecond) { if (startTimestamp < block.timestamp) revert BaseRewarder__InvalidStartTimestamp(startTimestamp); if (_isStopped) revert BaseRewarder__Stopped(); if (expectedDuration == 0 && maxRewardPerSecond != 0) revert BaseRewarder__InvalidDuration(); uint256 totalUnclaimedRewards = _totalUnclaimedRewards; uint256 totalSupply = _getTotalSupply(); uint256 totalRewards = _rewarder.getTotalRewards(_rewardsPerSecond, _endTimestamp, totalSupply); totalUnclaimedRewards += totalRewards; uint256 remainingReward = _balanceOfThis(_token()) - totalUnclaimedRewards; uint256 maxExpectedReward = maxRewardPerSecond * expectedDuration; rewardPerSecond = maxExpectedReward > remainingReward ? remainingReward / expectedDuration : maxRewardPerSecond; uint256 expectedReward = rewardPerSecond * expectedDuration; if (expectedDuration != 0 && expectedReward == 0) revert BaseRewarder__ZeroReward(); uint256 endTimestamp = startTimestamp + expectedDuration; _rewardsPerSecond = rewardPerSecond; _reserve = totalUnclaimedRewards + expectedReward; _endTimestamp = endTimestamp; _totalUnclaimedRewards = totalUnclaimedRewards; _rewarder.updateAccDebtPerShare(totalSupply, totalRewards); _rewarder.lastUpdateTimestamp = startTimestamp; emit RewardParameterUpdated(rewardPerSecond, startTimestamp, endTimestamp); } /** * @dev Reverts if the contract receives native tokens and the rewarder is not native. */ function _nativeReceived() internal view virtual { if (address(_token()) != address(0)) revert BaseRewarder__NotNativeRewarder(); } /** * @dev Returns the total supply of the staking pool. * Used to calculate the rewards when setting the reward per second. * Must be implemented by child contracts. * @return The total supply of the staking pool. */ function _getTotalSupply() internal view virtual returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {Amounts} from "./Amounts.sol"; import {Constants} from "./Constants.sol"; /** * @title Rewarder Library * @dev A library that defines various functions for calculating rewards. * It takes care about the reward debt and the accumulated debt per share. */ library Rewarder { using Amounts for Amounts.Parameter; struct Parameter { uint256 lastUpdateTimestamp; uint256 accDebtPerShare; mapping(address => uint256) debt; } /** * @dev Returns the debt associated with an amount. * @param accDebtPerShare The accumulated debt per share. * @param deposit The amount. * @return The debt associated with the amount. */ function getDebt(uint256 accDebtPerShare, uint256 deposit) internal pure returns (uint256) { return (deposit * accDebtPerShare) >> Constants.ACC_PRECISION_BITS; } /** * @dev Returns the debt per share associated with a total deposit and total rewards. * @param totalDeposit The total deposit. * @param totalRewards The total rewards. * @return The debt per share associated with the total deposit and total rewards. */ function getDebtPerShare(uint256 totalDeposit, uint256 totalRewards) internal pure returns (uint256) { return totalDeposit == 0 ? 0 : (totalRewards << Constants.ACC_PRECISION_BITS) / totalDeposit; } /** * @dev Returns the total rewards to emit. * If the end timestamp is in the past, the rewards are calculated up to the end timestamp. * If the last update timestamp is in the future, it will return 0. * @param rewarder The storage pointer to the rewarder. * @param rewardPerSecond The reward per second. * @param endTimestamp The end timestamp. * @param totalSupply The total supply. * @return The total rewards. */ function getTotalRewards( Parameter storage rewarder, uint256 rewardPerSecond, uint256 endTimestamp, uint256 totalSupply ) internal view returns (uint256) { if (totalSupply == 0) return 0; uint256 lastUpdateTimestamp = rewarder.lastUpdateTimestamp; uint256 timestamp = block.timestamp > endTimestamp ? endTimestamp : block.timestamp; return timestamp > lastUpdateTimestamp ? (timestamp - lastUpdateTimestamp) * rewardPerSecond : 0; } /** * @dev Returns the total rewards to emit. * @param rewarder The storage pointer to the rewarder. * @param rewardPerSecond The reward per second. * @param totalSupply The total supply. * @return The total rewards. */ function getTotalRewards(Parameter storage rewarder, uint256 rewardPerSecond, uint256 totalSupply) internal view returns (uint256) { return getTotalRewards(rewarder, rewardPerSecond, block.timestamp, totalSupply); } /** * @dev Returns the pending reward of an account. * @param rewarder The storage pointer to the rewarder. * @param amounts The storage pointer to the amounts. * @param account The address of the account. * @param totalRewards The total rewards. * @return The pending reward of the account. */ function getPendingReward( Parameter storage rewarder, Amounts.Parameter storage amounts, address account, uint256 totalRewards ) internal view returns (uint256) { return getPendingReward(rewarder, account, amounts.getAmountOf(account), amounts.getTotalAmount(), totalRewards); } /** * @dev Returns the pending reward of an account. * If the balance of the account is 0, it will always return 0. * @param rewarder The storage pointer to the rewarder. * @param account The address of the account. * @param balance The balance of the account. * @param totalSupply The total supply. * @param totalRewards The total rewards. * @return The pending reward of the account. */ function getPendingReward( Parameter storage rewarder, address account, uint256 balance, uint256 totalSupply, uint256 totalRewards ) internal view returns (uint256) { uint256 accDebtPerShare = rewarder.accDebtPerShare + getDebtPerShare(totalSupply, totalRewards); return balance == 0 ? 0 : getDebt(accDebtPerShare, balance) - rewarder.debt[account]; } /** * @dev Updates the rewarder. * If the balance of the account is 0, it will always return 0. * @param rewarder The storage pointer to the rewarder. * @param account The address of the account. * @param oldBalance The old balance of the account. * @param newBalance The new balance of the account. * @param totalSupply The total supply. * @param totalRewards The total rewards. * @return rewards The rewards of the account. */ function update( Parameter storage rewarder, address account, uint256 oldBalance, uint256 newBalance, uint256 totalSupply, uint256 totalRewards ) internal returns (uint256 rewards) { uint256 accDebtPerShare = updateAccDebtPerShare(rewarder, totalSupply, totalRewards); rewards = oldBalance == 0 ? 0 : getDebt(accDebtPerShare, oldBalance) - rewarder.debt[account]; rewarder.debt[account] = getDebt(accDebtPerShare, newBalance); } /** * @dev Updates the accumulated debt per share. * If the last update timestamp is in the future, it will not update the last update timestamp. * @param rewarder The storage pointer to the rewarder. * @param totalSupply The total supply. * @param totalRewards The total rewards. * @return The accumulated debt per share. */ function updateAccDebtPerShare(Parameter storage rewarder, uint256 totalSupply, uint256 totalRewards) internal returns (uint256) { uint256 debtPerShare = getDebtPerShare(totalSupply, totalRewards); if (block.timestamp > rewarder.lastUpdateTimestamp) rewarder.lastUpdateTimestamp = block.timestamp; return debtPerShare == 0 ? rewarder.accDebtPerShare : rewarder.accDebtPerShare += debtPerShare; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; import {IRewarder} from "./IRewarder.sol"; interface IBaseRewarder is IRewarder { error BaseRewarder__NativeTransferFailed(); error BaseRewarder__InvalidCaller(); error BaseRewarder__Stopped(); error BaseRewarder__AlreadyStopped(); error BaseRewarder__NotNativeRewarder(); error BaseRewarder__ZeroAmount(); error BaseRewarder__ZeroReward(); error BaseRewarder__InvalidDuration(); error BaseRewarder__InvalidPid(uint256 pid); error BaseRewarder__InvalidStartTimestamp(uint256 startTimestamp); error BaseRewarder__CannotRenounceOwnership(); event Claim(address indexed account, IERC20 indexed token, uint256 reward); event RewardParameterUpdated(uint256 rewardPerSecond, uint256 startTimestamp, uint256 endTimestamp); event Stopped(); event Swept(IERC20 indexed token, address indexed account, uint256 amount); function getToken() external view returns (IERC20); function getCaller() external view returns (address); function getPid() external view returns (uint256); function getRewarderParameter() external view returns (IERC20 token, uint256 rewardPerSecond, uint256 lastUpdateTimestamp, uint256 endTimestamp); function getRemainingReward() external view returns (uint256); function getPendingReward(address account, uint256 balance, uint256 totalSupply) external view returns (IERC20 token, uint256 pendingReward); function isStopped() external view returns (bool); function initialize(address initialOwner) external; function setRewardPerSecond(uint256 maxRewardPerSecond, uint256 expectedDuration) external returns (uint256 rewardPerSecond); function setRewarderParameters(uint256 maxRewardPerSecond, uint256 startTimestamp, uint256 expectedDuration) external returns (uint256 rewardPerSecond); function stop() external; function sweep(IERC20 token, address account) external; function onModify(address account, uint256 pid, uint256 oldBalance, uint256 newBalance, uint256 totalSupply) external returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; interface IMetro is IERC20 { function mint(address account, uint256 amount) external returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {IBribeRewarder} from "./IBribeRewarder.sol"; import {IMasterChef} from "./IMasterChef.sol"; interface IVoter { error IVoter__InvalidLength(); error IVoter_VotingPeriodNotStarted(); error IVoter_VotingPeriodEnded(); error IVoter__AlreadyVoted(); error IVoter__NotOwner(); error IVoter__InsufficientVotingPower(); error IVoter__TooManyPoolIds(); error IVoter__DuplicatePoolId(uint256 pid); error IVoter__InsufficientLockTime(); error Voter__InvalidRegisterCaller(); error Voter__PoolNotVotable(); error IVoter__NoFinishedPeriod(); error IVoter_ZeroValue(); error IVoter__EmergencyUnlock(); event VotingPeriodStarted(); event Voted(uint256 indexed tokenId, uint256 votingPeriod, address[] votedPools, uint256[] votesDeltaAmounts); event TopPoolIdsWithWeightsSet(uint256[] poolIds, uint256[] pidWeights); event VoterPoolValidatorUpdated(address indexed validator); event VotingDurationUpdated(uint256 duration); event MinimumLockTimeUpdated(uint256 lockTime); event MinimumVotesPerPoolUpdated(uint256 minimum); event OperatorUpdated(address indexed operator); event ElevatedRewarderAdded(address indexed rewarder); event ElevatedRewarderRemoved(address indexed rewarder); struct VotingPeriod { uint256 startTime; uint256 endTime; } function getMasterChef() external view returns (IMasterChef); function getTotalWeight() external view returns (uint256); function getTopPoolIds() external view returns (uint256[] memory); function getWeight(uint256 pid) external view returns (uint256); function hasVoted(uint256 period, uint256 tokenId) external view returns (bool); function getCurrentVotingPeriod() external view returns (uint256); function getLatestFinishedPeriod() external view returns (uint256); function getPeriodStartTime() external view returns (uint256); function getPeriodStartEndtime(uint256 periodId) external view returns (uint256, uint256); function getVotesPerPeriod(uint256 periodId, address pool) external view returns (uint256); function getVotedPools() external view returns (address[] memory); function getVotedPoolsLength() external view returns (uint256); function getVotedPoolsAtIndex(uint256 index) external view returns (address, uint256); function getTotalVotes() external view returns (uint256); function getUserVotes(uint256 tokenId, address pool) external view returns (uint256); function getPoolVotesPerPeriod(uint256 periodId, address pool) external view returns (uint256); function getUserBribeRewaderAt(uint256 period, address account, uint256 index) external view returns (IBribeRewarder); function getUserBribeRewarderLength(uint256 period, address account) external view returns (uint256); function getBribeRewarderAt(uint256 period, address pool, uint256 index) external view returns (IBribeRewarder); function getBribeRewarderLength(uint256 period, address pool) external view returns (uint256); function ownerOf(uint256 tokenId, address account) external view returns (bool); function onRegister() external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {Math} from "./Math.sol"; /** * @title Amounts Library * @dev A library that defines various functions for manipulating amounts of a key and a total. * The key can be bytes32, address, or uint256. */ library Amounts { using Math for uint256; struct Parameter { uint256 totalAmount; mapping(bytes32 => uint256) amounts; } /** * @dev Returns the amount of a key. * @param amounts The storage pointer to the amounts. * @param key The key of the amount. * @return The amount of the key. */ function getAmountOf(Parameter storage amounts, bytes32 key) internal view returns (uint256) { return amounts.amounts[key]; } /** * @dev Returns the amount of an address. * @param amounts The storage pointer to the amounts. * @param account The address of the amount. * @return The amount of the address. */ function getAmountOf(Parameter storage amounts, address account) internal view returns (uint256) { return getAmountOf(amounts, bytes32(uint256(uint160(account)))); } /** * @dev Returns the amount of an id. * @param amounts The storage pointer to the amounts. * @param id The id of the amount. * @return The amount of the id. */ function getAmountOf(Parameter storage amounts, uint256 id) internal view returns (uint256) { return getAmountOf(amounts, bytes32(id)); } /** * @dev Returns the total amount. * @param amounts The storage pointer to the amounts. * @return The total amount. */ function getTotalAmount(Parameter storage amounts) internal view returns (uint256) { return amounts.totalAmount; } /** * @dev Updates the amount of a key. The delta is added to the key amount and the total amount. * @param amounts The storage pointer to the amounts. * @param key The key of the amount. * @param deltaAmount The delta amount to update. * @return oldAmount The old amount of the key. * @return newAmount The new amount of the key. * @return oldTotalAmount The old total amount. * @return newTotalAmount The new total amount. */ function update(Parameter storage amounts, bytes32 key, int256 deltaAmount) internal returns (uint256 oldAmount, uint256 newAmount, uint256 oldTotalAmount, uint256 newTotalAmount) { oldAmount = amounts.amounts[key]; oldTotalAmount = amounts.totalAmount; if (deltaAmount == 0) { newAmount = oldAmount; newTotalAmount = oldTotalAmount; } else { newAmount = oldAmount.addDelta(deltaAmount); newTotalAmount = oldTotalAmount.addDelta(deltaAmount); amounts.amounts[key] = newAmount; amounts.totalAmount = newTotalAmount; } } /** * @dev Updates the amount of an address. The delta is added to the address amount and the total amount. * @param amounts The storage pointer to the amounts. * @param account The address of the amount. * @param deltaAmount The delta amount to update. * @return oldAmount The old amount of the key. * @return newAmount The new amount of the key. * @return oldTotalAmount The old total amount. * @return newTotalAmount The new total amount. */ function update(Parameter storage amounts, address account, int256 deltaAmount) internal returns (uint256 oldAmount, uint256 newAmount, uint256 oldTotalAmount, uint256 newTotalAmount) { return update(amounts, bytes32(uint256(uint160(account))), deltaAmount); } /** * @dev Updates the amount of an id. The delta is added to the id amount and the total amount. * @param amounts The storage pointer to the amounts. * @param id The id of the amount. * @param deltaAmount The delta amount to update. * @return oldAmount The old amount of the key. * @return newAmount The new amount of the key. * @return oldTotalAmount The old total amount. * @return newTotalAmount The new total amount. */ function update(Parameter storage amounts, uint256 id, int256 deltaAmount) internal returns (uint256 oldAmount, uint256 newAmount, uint256 oldTotalAmount, uint256 newTotalAmount) { return update(amounts, bytes32(id), deltaAmount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; import {IRewarder} from "../interfaces/IRewarder.sol"; import {IBribeRewarder} from "../interfaces/IBribeRewarder.sol"; import {IBaseRewarder} from "../interfaces/IBaseRewarder.sol"; interface IRewarderFactory { error RewarderFactory__ZeroAddress(); error RewarderFactory__InvalidRewarderType(); error RewarderFactory__InvalidPid(); error RewarderFactory__TokenNotWhitelisted(); error RewarderFactory__InvalidLength(); enum RewarderType { InvalidRewarder, MasterChefRewarder, BribeRewarder } event RewarderCreated( RewarderType indexed rewarderType, IERC20 indexed token, uint256 indexed pid, IBaseRewarder rewarder ); event BribeRewarderCreated( RewarderType indexed rewarderType, IERC20 indexed token, address indexed pool, IBribeRewarder rewarder ); event RewarderImplementationSet(RewarderType indexed rewarderType, IRewarder indexed implementation); function getBribeCreatorFee() external view returns (uint256); function getWhitelistedTokenInfo (address token) external view returns (bool, uint256); function getRewarderImplementation(RewarderType rewarderType) external view returns (IRewarder); function getRewarderCount(RewarderType rewarderType) external view returns (uint256); function getRewarderAt(RewarderType rewarderType, uint256 index) external view returns (IRewarder); function getRewarderType(IRewarder rewarder) external view returns (RewarderType); function setRewarderImplementation(RewarderType rewarderType, IRewarder implementation) external; function createRewarder(RewarderType rewarderType, IERC20 token, uint256 pid) external returns (IBaseRewarder); function createBribeRewarder(IERC20 token, address pool) external returns (IBribeRewarder); function setWhitelist(address[] calldata tokens, uint256[] calldata minBribeAmounts) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol) pragma solidity ^0.8.20; import {OwnableUpgradeable} from "./OwnableUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is specified at deployment time in the constructor for `Ownable`. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable2Step struct Ownable2StepStorage { address _pendingOwner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable2Step")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant Ownable2StepStorageLocation = 0x237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00; function _getOwnable2StepStorage() private pure returns (Ownable2StepStorage storage $) { assembly { $.slot := Ownable2StepStorageLocation } } event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); function __Ownable2Step_init() internal onlyInitializing { } function __Ownable2Step_init_unchained() internal onlyInitializing { } /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); return $._pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); $._pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); delete $._pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /** * @title Clone * @notice Class with helper read functions for clone with immutable args. * @author Trader Joe * @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Clone.sol) * @author Adapted from clones with immutable args by zefram.eth, Saw-mon & Natalie * (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args) */ abstract contract Clone { /** * @dev Reads an immutable arg with type bytes * @param argOffset The offset of the arg in the immutable args * @param length The length of the arg * @return arg The immutable bytes arg */ function _getArgBytes(uint256 argOffset, uint256 length) internal pure returns (bytes memory arg) { uint256 offset = _getImmutableArgsOffset(); /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. arg := mload(0x40) // Store the array length. mstore(arg, length) // Copy the array. calldatacopy(add(arg, 0x20), add(offset, argOffset), length) // Allocate the memory, rounded up to the next 32 byte boundary. mstore(0x40, and(add(add(arg, 0x3f), length), not(0x1f))) } } /** * @dev Reads an immutable arg with type address * @param argOffset The offset of the arg in the immutable args * @return arg The immutable address arg */ function _getArgAddress(uint256 argOffset) internal pure returns (address arg) { uint256 offset = _getImmutableArgsOffset(); /// @solidity memory-safe-assembly assembly { arg := shr(0x60, calldataload(add(offset, argOffset))) } } /** * @dev Reads an immutable arg with type uint256 * @param argOffset The offset of the arg in the immutable args * @return arg The immutable uint256 arg */ function _getArgUint256(uint256 argOffset) internal pure returns (uint256 arg) { uint256 offset = _getImmutableArgsOffset(); /// @solidity memory-safe-assembly assembly { arg := calldataload(add(offset, argOffset)) } } /** * @dev Reads a uint256 array stored in the immutable args. * @param argOffset The offset of the arg in the immutable args * @param length The length of the arg * @return arg The immutable uint256 array arg */ function _getArgUint256Array(uint256 argOffset, uint256 length) internal pure returns (uint256[] memory arg) { uint256 offset = _getImmutableArgsOffset(); /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. arg := mload(0x40) // Store the array length. mstore(arg, length) // Copy the array. calldatacopy(add(arg, 0x20), add(offset, argOffset), shl(5, length)) // Allocate the memory. mstore(0x40, add(add(arg, 0x20), shl(5, length))) } } /** * @dev Reads an immutable arg with type uint64 * @param argOffset The offset of the arg in the immutable args * @return arg The immutable uint64 arg */ function _getArgUint64(uint256 argOffset) internal pure returns (uint64 arg) { uint256 offset = _getImmutableArgsOffset(); /// @solidity memory-safe-assembly assembly { arg := shr(0xc0, calldataload(add(offset, argOffset))) } } /** * @dev Reads an immutable arg with type uint16 * @param argOffset The offset of the arg in the immutable args * @return arg The immutable uint16 arg */ function _getArgUint16(uint256 argOffset) internal pure returns (uint16 arg) { uint256 offset = _getImmutableArgsOffset(); /// @solidity memory-safe-assembly assembly { arg := shr(0xf0, calldataload(add(offset, argOffset))) } } /** * @dev Reads an immutable arg with type uint8 * @param argOffset The offset of the arg in the immutable args * @return arg The immutable uint8 arg */ function _getArgUint8(uint256 argOffset) internal pure returns (uint8 arg) { uint256 offset = _getImmutableArgsOffset(); /// @solidity memory-safe-assembly assembly { arg := shr(0xf8, calldataload(add(offset, argOffset))) } } /** * @dev Reads the offset of the packed immutable args in calldata. * @return offset The offset of the packed immutable args in calldata. */ function _getImmutableArgsOffset() internal pure returns (uint256 offset) { /// @solidity memory-safe-assembly assembly { offset := sub(calldatasize(), shr(0xf0, calldataload(sub(calldatasize(), 2)))) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @title Constants Library * @dev A library that defines various constants used throughout the codebase. */ library Constants { uint256 internal constant ACC_PRECISION_BITS = 64; uint256 internal constant PRECISION = 1e18; uint256 internal constant MAX_NUMBER_OF_FARMS = 32; uint256 internal constant MAX_NUMBER_OF_REWARDS = 32; uint256 internal constant MAX_METRO_PER_SECOND = 10e18; uint256 internal constant MAX_BRIBES_PER_POOL = 5; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; interface IRewarder { function getToken() external view returns (IERC20); function getCaller() external view returns (address); function initialize(address initialOwner) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; import {IRewarder} from "./IRewarder.sol"; interface IBribeRewarder is IRewarder { error BribeRewarder__OnlyVoter(); error BribeRewarder__InsufficientFunds(); error BribeRewarder__WrongStartId(); error BribeRewarder__WrongEndId(); error BribeRewarder__ZeroReward(); error BribeRewarder__NativeTransferFailed(); error BribeRewarder__NotOwner(); error BribeRewarder__CannotRenounceOwnership(); error BribeRewarder__NotNativeRewarder(); error BribeRewarder__AlreadyInitialized(); error BribeRewarder__PeriodNotFound(); error BribeRewarder__AmountTooLow(); error BribeRewarder__OnlyVoterAdmin(); event Claimed(address indexed account, address indexed pool, uint256 amount); event Deposited(uint256 indexed periodId, address indexed account, address indexed pool, uint256 amount); event BribeInit(uint256 indexed startId, uint256 indexed lastId, uint256 amountPerPeriod); event Swept(IERC20 indexed token, address indexed account, uint256 amount); function bribe(uint256 startId, uint256 lastId, uint256 amountPerPeriod) external; function claim(address account) external; function deposit(uint256 periodId, address account, uint256 deltaAmount) external; function getPool() external view returns (address); function getPendingReward(address account) external view returns (uint256); function getBribePeriods() external view returns (address pool, uint256[] memory); function getStartVotingPeriodId() external view returns (uint256); function getLastVotingPeriodId() external view returns (uint256); function getAmountPerPeriod() external view returns (uint256); function sweep(IERC20 token, address account) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @title Math * @dev Library for mathematical operations with overflow and underflow checks. */ library Math { error Math__UnderOverflow(); uint256 internal constant MAX_INT256 = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; /** * @dev Adds a signed integer to an unsigned integer with overflow check. * The result must be greater than or equal to 0 and less than or equal to MAX_INT256. * @param x Unsigned integer to add to. * @param delta Signed integer to add. * @return y The result of the addition. */ function addDelta(uint256 x, int256 delta) internal pure returns (uint256 y) { uint256 success; assembly { y := add(x, delta) success := iszero(or(gt(x, MAX_INT256), gt(y, MAX_INT256))) } if (success == 0) revert Math__UnderOverflow(); } /** * @dev Safely converts an unsigned integer to a signed integer. * @param x Unsigned integer to convert. * @return y Signed integer result. */ function toInt256(uint256 x) internal pure returns (int256 y) { if (x > MAX_INT256) revert Math__UnderOverflow(); return int256(x); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "openzeppelin/=lib/openzeppelin-contracts/contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "solmate/=lib/solmate/", "joe-v2/=lib/joe-v2/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 800 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"BaseRewarder__AlreadyStopped","type":"error"},{"inputs":[],"name":"BaseRewarder__CannotRenounceOwnership","type":"error"},{"inputs":[],"name":"BaseRewarder__InvalidCaller","type":"error"},{"inputs":[],"name":"BaseRewarder__InvalidDuration","type":"error"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"}],"name":"BaseRewarder__InvalidPid","type":"error"},{"inputs":[{"internalType":"uint256","name":"startTimestamp","type":"uint256"}],"name":"BaseRewarder__InvalidStartTimestamp","type":"error"},{"inputs":[],"name":"BaseRewarder__NativeTransferFailed","type":"error"},{"inputs":[],"name":"BaseRewarder__NotNativeRewarder","type":"error"},{"inputs":[],"name":"BaseRewarder__Stopped","type":"error"},{"inputs":[],"name":"BaseRewarder__ZeroAmount","type":"error"},{"inputs":[],"name":"BaseRewarder__ZeroReward","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"MasterChefRewarder__AlreadyLinked","type":"error"},{"inputs":[],"name":"MasterChefRewarder__NotLinked","type":"error"},{"inputs":[],"name":"MasterChefRewarder__UseUnlink","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"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":"rewardPerSecond","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTimestamp","type":"uint256"}],"name":"RewardParameterUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"Stopped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Swept","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCaller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"}],"name":"getPendingReward","outputs":[{"internalType":"contract IERC20","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRemainingReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewarderParameter","outputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"rewardPerSecond","type":"uint256"},{"internalType":"uint256","name":"lastUpdateTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isStopped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"}],"name":"link","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"pid","type":"uint256"},{"internalType":"uint256","name":"oldBalance","type":"uint256"},{"internalType":"uint256","name":"newBalance","type":"uint256"},{"internalType":"uint256","name":"oldTotalSupply","type":"uint256"}],"name":"onEmergency","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"pid","type":"uint256"},{"internalType":"uint256","name":"oldBalance","type":"uint256"},{"internalType":"uint256","name":"newBalance","type":"uint256"},{"internalType":"uint256","name":"oldTotalSupply","type":"uint256"}],"name":"onModify","outputs":[{"internalType":"uint256","name":"reward","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxRewardPerSecond","type":"uint256"},{"internalType":"uint256","name":"expectedDuration","type":"uint256"}],"name":"setRewardPerSecond","outputs":[{"internalType":"uint256","name":"rewardPerSecond","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxRewardPerSecond","type":"uint256"},{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"expectedDuration","type":"uint256"}],"name":"setRewarderParameters","outputs":[{"internalType":"uint256","name":"rewardPerSecond","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stop","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"}],"name":"unlink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60c06040523480156200001157600080fd5b5060405162001ac738038062001ac783398101604081905262000034916200010c565b6001600160a01b03811660a05230608052806200005062000058565b50506200013e565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff1615620000a95760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b0390811614620001095780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b6000602082840312156200011f57600080fd5b81516001600160a01b03811681146200013757600080fd5b9392505050565b60805160a051611940620001876000396000818161032a0152818161062701528181610a3f01528181610b4a01528181610cf801526110a30152600061026c01526119406000f3fe6080604052600436106101795760003560e01c8063b1a867d5116100cb578063c71832511161007f578063e30c397811610059578063e30c397814610464578063f1e023fd14610479578063f2fde38b1461049957610188565b8063c7183251146103e3578063c877296314610422578063dc6c42261461044457610188565b8063b8dc491b116100b0578063b8dc491b1461038e578063c0b5fca0146103ae578063c4d66de8146103c357610188565b8063b1a867d51461034e578063b5f578fc1461036e57610188565b8063715018a61161012d57806389f5ab0d1161010757806389f5ab0d146102e65780638da5cb5b14610306578063ab470f051461031b57610188565b8063715018a61461028e57806379ba5097146102a3578063870b50fd146102b857610188565b806339cbec9d1161015e57806339cbec9d146101e05780633f683b6a146102375780635c60da1b1461025a57610188565b806307da68f51461019057806321df0da7146101a557610188565b36610188576101866104b9565b005b6101866104b9565b34801561019c57600080fd5b506101866104e9565b3480156101b157600080fd5b503660011981013560f01c90033560601c5b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101ec57600080fd5b5061020d600054600554600354600119369081013560f01c90033560601c93565b604080516001600160a01b03909516855260208501939093529183015260608201526080016101d7565b34801561024357600080fd5b5060045460ff1660405190151581526020016101d7565b34801561026657600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b34801561029a57600080fd5b50610186610507565b3480156102af57600080fd5b50610186610520565b3480156102c457600080fd5b506102d86102d33660046116df565b61056d565b6040519081526020016101d7565b3480156102f257600080fd5b506102d8610301366004611723565b6105c8565b34801561031257600080fd5b506101c36105e7565b34801561032757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b34801561035a57600080fd5b5061018661036936600461174f565b61061c565b34801561037a57600080fd5b506102d8610389366004611768565b610702565b34801561039a57600080fd5b506101866103a936600461178a565b610738565b3480156103ba57600080fd5b506102d861082a565b3480156103cf57600080fd5b506101866103de3660046117c3565b610894565b3480156103ef57600080fd5b506104036103fe3660046117e0565b6109b8565b604080516001600160a01b0390931683526020830191909152016101d7565b34801561042e57600080fd5b503660011981013560f01c9003601401356102d8565b34801561045057600080fd5b5061018661045f3660046116df565b6109fd565b34801561047057600080fd5b506101c3610b16565b34801561048557600080fd5b5061018661049436600461174f565b610b3f565b3480156104a557600080fd5b506101866104b43660046117c3565b610c10565b3660011981013560f01c90033560601c156104e757604051639415816f60e01b815260040160405180910390fd5b565b60405163f92ad2c760e01b815260040160405180910390fd5b905090565b6040516313e3bb6f60e21b815260040160405180910390fd5b338061052a610b16565b6001600160a01b0316146105615760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b61056a81610ca2565b50565b6000600160085460ff16600281111561058857610588611815565b146105a65760405163d0ef47e760e01b815260040160405180910390fd5b6105b38686868686610ceb565b90506105bf8682610d7e565b95945050505050565b60006105d2610dde565b6105dd848484610e10565b90505b9392505050565b6000807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005b546001600160a01b031692915050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106655760405163332bf49d60e21b815260040160405180910390fd5b600060085460ff16600281111561067e5761067e611815565b1461069c57604051630d85b6ed60e01b815260040160405180910390fd5b3660011981013560f01c90036014013581146106ce5760405163e7ca808760e01b815260048101829052602401610558565b60045460ff16156106f257604051630f3e8c1360e11b815260040160405180910390fd5b506008805460ff19166001179055565b600061070c610dde565b600554600042821161071e5742610720565b815b905061072d858286610e10565b925050505b92915050565b610740610dde565b600061074b83610fd2565b90503660011981013560f01c90033560601c6001600160a01b038416036107ac5760045460ff161561079c576000610781611057565b1115610797576001546107949082611841565b90505b6107ac565b6002546107a99082611841565b90505b806000036107cd576040516360e6da0360e01b815260040160405180910390fd5b6107d8838383611114565b816001600160a01b0316836001600160a01b03167f7b09c29f9106defeccc9ac3b823f3aad0b470d120e5df7aed033b5c43a4bf7188360405161081d91815260200190565b60405180910390a3505050565b600080610835611057565b905060006108556000546003548460056111c2909392919063ffffffff16565b90506000816001546108679190611854565b9050806108823660011981013560f01c90033560601c610fd2565b61088c9190611841565b935050505090565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff166000811580156108df5750825b905060008267ffffffffffffffff1660011480156108fc5750303b155b90508115801561090a575080155b156109285760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561095c57845468ff00000000000000001916680100000000000000001785555b61096586611219565b83156109b057845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b60008054600354829182916109d091600591876111c2565b90503660011981013560f01c90033560601c6109f060058888888661122a565b9250925050935093915050565b600160085460ff166002811115610a1657610a16611815565b14610a345760405163d0ef47e760e01b815260040160405180910390fd5b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a7d5760405163332bf49d60e21b815260040160405180910390fd5b3660011981013560f01c9003601401358414610aaf5760405163e7ca808760e01b815260048101859052602401610558565b60008115610acf57600054600354610aca91600591856111c2565b610ad2565b60005b90506000610ae560058887878787611290565b905081600154610af59190611854565b600155610b0c610b03611057565b60059083611314565b5050505050505050565b6000807f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c0061060c565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b885760405163332bf49d60e21b815260040160405180910390fd5b3660011981013560f01c9003601401358114610bba5760405163e7ca808760e01b815260048101829052602401610558565b600160085460ff166002811115610bd357610bd3611815565b14610bf15760405163d0ef47e760e01b815260040160405180910390fd5b506008805460ff19908116600217909155600480549091166001179055565b610c18610dde565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081178255610c696105e7565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a35050565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00805473ffffffffffffffffffffffffffffffffffffffff19168155610ce782611364565b5050565b6000336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d365760405163332bf49d60e21b815260040160405180910390fd5b3660011981013560f01c9003601401358514610d685760405163e7ca808760e01b815260048101869052602401610558565b610d74868585856113e2565b9695505050505050565b3660011981013560f01c90033560601c610d99818484611114565b806001600160a01b0316836001600160a01b03167f70eb43c4a8ae8c40502dcf22436c509c28d6ff421cf07c491be56984bd9870688460405161081d91815260200190565b33610de76105e7565b6001600160a01b0316146104e75760405163118cdaa760e01b8152336004820152602401610558565b600042831015610e3657604051635c62004b60e11b815260048101849052602401610558565b60045460ff1615610e5a57604051630f3e8c1360e11b815260040160405180910390fd5b81158015610e6757508315155b15610e8557604051631a4778f160e31b815260040160405180910390fd5b6001546000610e92611057565b90506000610eb26000546003548460056111c2909392919063ffffffff16565b9050610ebe8184611854565b9250600083610edb3660011981013560f01c90033560601c610fd2565b610ee59190611841565b90506000610ef3878a611867565b9050818111610f025788610f0c565b610f0c878361187e565b95506000610f1a8888611867565b90508715801590610f29575080155b15610f4757604051634ef6878160e01b815260040160405180910390fd5b6000610f53898b611854565b60008990559050610f648288611854565b60025560038190556001879055610f7d60058787611314565b5060058a905560408051898152602081018c90529081018290527ff0b276e9ee40b3a3d065f636ee656c9bf1c9a0c4060fb212fd0861890c107be59060600160405180910390a1505050505050509392505050565b60006001600160a01b03821615611050576040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611027573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104b91906118a0565b610732565b4792915050565b6000600160085460ff16600281111561107257611072611815565b0361110e5760405163691d5cbd60e11b81523660011981013560f01c90036014013560048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d23ab97a90602401602060405180830381865afa1580156110ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050291906118a0565b50600090565b8060000361112157505050565b6001600160a01b0383166111a9576000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461117c576040519150601f19603f3d011682016040523d82523d6000602084013e611181565b606091505b50509050806111a357604051630df61d5560e01b815260040160405180910390fd5b50505050565b6111bd6001600160a01b0384168383611452565b505050565b6000816000036111d457506000611211565b845460004285106111e557426111e7565b845b90508181116111f757600061120c565b856112028383611841565b61120c9190611867565b925050505b949350505050565b6112216114b9565b61056a81611507565b6000806112378484611539565b87600101546112469190611854565b90508415611282576001600160a01b0386166000908152600288016020526040902054611273828761155d565b61127d9190611841565b611285565b60005b979650505050505050565b60008061129e888585611314565b905085156112da576001600160a01b03871660009081526002890160205260409020546112cb828861155d565b6112d59190611841565b6112dd565b60005b91506112e9818661155d565b6001600160a01b03909716600090815260029098016020525060409096209490945550929392505050565b6000806113218484611539565b8554909150421115611331574285555b8015611356578085600101600082825461134b9190611854565b9250508190556105bf565b846001015495945050505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6001546002546000919082841561140b5760005460035461140691600591886111c2565b61140e565b60005b905061141f60058989898986611290565b93508361142c8285611854565b6114369190611841565b6001556114438483611841565b60025550919695505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b1790526111bd908490611574565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166104e757604051631afcd79f60e31b815260040160405180910390fd5b61150f6114b9565b6001600160a01b03811661056157604051631e4fbdf760e01b815260006004820152602401610558565b600082156115545761154f83604084901b61187e565b6105e0565b60009392505050565b6000604061156b8484611867565b901c9392505050565b60006115896001600160a01b038416836115d7565b905080516000141580156115ae5750808060200190518101906115ac91906118b9565b155b156111bd57604051635274afe760e01b81526001600160a01b0384166004820152602401610558565b60606105e08383600084600080856001600160a01b031684866040516115fd91906118db565b60006040518083038185875af1925050503d806000811461163a576040519150601f19603f3d011682016040523d82523d6000602084013e61163f565b606091505b5091509150610d7486838360608261165a5761154f826116a1565b815115801561167157506001600160a01b0384163b155b1561169a57604051639996b31560e01b81526001600160a01b0385166004820152602401610558565b50806105e0565b8051156116b15780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b038116811461056a57600080fd5b600080600080600060a086880312156116f757600080fd5b8535611702816116ca565b97602087013597506040870135966060810135965060800135945092505050565b60008060006060848603121561173857600080fd5b505081359360208301359350604090920135919050565b60006020828403121561176157600080fd5b5035919050565b6000806040838503121561177b57600080fd5b50508035926020909101359150565b6000806040838503121561179d57600080fd5b82356117a8816116ca565b915060208301356117b8816116ca565b809150509250929050565b6000602082840312156117d557600080fd5b81356105e0816116ca565b6000806000606084860312156117f557600080fd5b8335611800816116ca565b95602085013595506040909401359392505050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156107325761073261182b565b808201808211156107325761073261182b565b80820281158282048414176107325761073261182b565b60008261189b57634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156118b257600080fd5b5051919050565b6000602082840312156118cb57600080fd5b815180151581146105e057600080fd5b6000825160005b818110156118fc57602081860181015185830152016118e2565b50600092019182525091905056fea2646970667358221220e776b0d407c54e3cd0385bb49b48a32ef4db0c3ad6a1e8458a82d995ef490ac064736f6c6343000814003300000000000000000000000072a42e8a344eb66aca9ed13d5c633731cf54eeea
Deployed Bytecode
0x6080604052600436106101795760003560e01c8063b1a867d5116100cb578063c71832511161007f578063e30c397811610059578063e30c397814610464578063f1e023fd14610479578063f2fde38b1461049957610188565b8063c7183251146103e3578063c877296314610422578063dc6c42261461044457610188565b8063b8dc491b116100b0578063b8dc491b1461038e578063c0b5fca0146103ae578063c4d66de8146103c357610188565b8063b1a867d51461034e578063b5f578fc1461036e57610188565b8063715018a61161012d57806389f5ab0d1161010757806389f5ab0d146102e65780638da5cb5b14610306578063ab470f051461031b57610188565b8063715018a61461028e57806379ba5097146102a3578063870b50fd146102b857610188565b806339cbec9d1161015e57806339cbec9d146101e05780633f683b6a146102375780635c60da1b1461025a57610188565b806307da68f51461019057806321df0da7146101a557610188565b36610188576101866104b9565b005b6101866104b9565b34801561019c57600080fd5b506101866104e9565b3480156101b157600080fd5b503660011981013560f01c90033560601c5b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101ec57600080fd5b5061020d600054600554600354600119369081013560f01c90033560601c93565b604080516001600160a01b03909516855260208501939093529183015260608201526080016101d7565b34801561024357600080fd5b5060045460ff1660405190151581526020016101d7565b34801561026657600080fd5b506101c37f0000000000000000000000007a1d40864982f4d7c7151ea70b576efc404e82fe81565b34801561029a57600080fd5b50610186610507565b3480156102af57600080fd5b50610186610520565b3480156102c457600080fd5b506102d86102d33660046116df565b61056d565b6040519081526020016101d7565b3480156102f257600080fd5b506102d8610301366004611723565b6105c8565b34801561031257600080fd5b506101c36105e7565b34801561032757600080fd5b507f00000000000000000000000072a42e8a344eb66aca9ed13d5c633731cf54eeea6101c3565b34801561035a57600080fd5b5061018661036936600461174f565b61061c565b34801561037a57600080fd5b506102d8610389366004611768565b610702565b34801561039a57600080fd5b506101866103a936600461178a565b610738565b3480156103ba57600080fd5b506102d861082a565b3480156103cf57600080fd5b506101866103de3660046117c3565b610894565b3480156103ef57600080fd5b506104036103fe3660046117e0565b6109b8565b604080516001600160a01b0390931683526020830191909152016101d7565b34801561042e57600080fd5b503660011981013560f01c9003601401356102d8565b34801561045057600080fd5b5061018661045f3660046116df565b6109fd565b34801561047057600080fd5b506101c3610b16565b34801561048557600080fd5b5061018661049436600461174f565b610b3f565b3480156104a557600080fd5b506101866104b43660046117c3565b610c10565b3660011981013560f01c90033560601c156104e757604051639415816f60e01b815260040160405180910390fd5b565b60405163f92ad2c760e01b815260040160405180910390fd5b905090565b6040516313e3bb6f60e21b815260040160405180910390fd5b338061052a610b16565b6001600160a01b0316146105615760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b61056a81610ca2565b50565b6000600160085460ff16600281111561058857610588611815565b146105a65760405163d0ef47e760e01b815260040160405180910390fd5b6105b38686868686610ceb565b90506105bf8682610d7e565b95945050505050565b60006105d2610dde565b6105dd848484610e10565b90505b9392505050565b6000807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005b546001600160a01b031692915050565b336001600160a01b037f00000000000000000000000072a42e8a344eb66aca9ed13d5c633731cf54eeea16146106655760405163332bf49d60e21b815260040160405180910390fd5b600060085460ff16600281111561067e5761067e611815565b1461069c57604051630d85b6ed60e01b815260040160405180910390fd5b3660011981013560f01c90036014013581146106ce5760405163e7ca808760e01b815260048101829052602401610558565b60045460ff16156106f257604051630f3e8c1360e11b815260040160405180910390fd5b506008805460ff19166001179055565b600061070c610dde565b600554600042821161071e5742610720565b815b905061072d858286610e10565b925050505b92915050565b610740610dde565b600061074b83610fd2565b90503660011981013560f01c90033560601c6001600160a01b038416036107ac5760045460ff161561079c576000610781611057565b1115610797576001546107949082611841565b90505b6107ac565b6002546107a99082611841565b90505b806000036107cd576040516360e6da0360e01b815260040160405180910390fd5b6107d8838383611114565b816001600160a01b0316836001600160a01b03167f7b09c29f9106defeccc9ac3b823f3aad0b470d120e5df7aed033b5c43a4bf7188360405161081d91815260200190565b60405180910390a3505050565b600080610835611057565b905060006108556000546003548460056111c2909392919063ffffffff16565b90506000816001546108679190611854565b9050806108823660011981013560f01c90033560601c610fd2565b61088c9190611841565b935050505090565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff166000811580156108df5750825b905060008267ffffffffffffffff1660011480156108fc5750303b155b90508115801561090a575080155b156109285760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561095c57845468ff00000000000000001916680100000000000000001785555b61096586611219565b83156109b057845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b60008054600354829182916109d091600591876111c2565b90503660011981013560f01c90033560601c6109f060058888888661122a565b9250925050935093915050565b600160085460ff166002811115610a1657610a16611815565b14610a345760405163d0ef47e760e01b815260040160405180910390fd5b336001600160a01b037f00000000000000000000000072a42e8a344eb66aca9ed13d5c633731cf54eeea1614610a7d5760405163332bf49d60e21b815260040160405180910390fd5b3660011981013560f01c9003601401358414610aaf5760405163e7ca808760e01b815260048101859052602401610558565b60008115610acf57600054600354610aca91600591856111c2565b610ad2565b60005b90506000610ae560058887878787611290565b905081600154610af59190611854565b600155610b0c610b03611057565b60059083611314565b5050505050505050565b6000807f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c0061060c565b336001600160a01b037f00000000000000000000000072a42e8a344eb66aca9ed13d5c633731cf54eeea1614610b885760405163332bf49d60e21b815260040160405180910390fd5b3660011981013560f01c9003601401358114610bba5760405163e7ca808760e01b815260048101829052602401610558565b600160085460ff166002811115610bd357610bd3611815565b14610bf15760405163d0ef47e760e01b815260040160405180910390fd5b506008805460ff19908116600217909155600480549091166001179055565b610c18610dde565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081178255610c696105e7565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a35050565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00805473ffffffffffffffffffffffffffffffffffffffff19168155610ce782611364565b5050565b6000336001600160a01b037f00000000000000000000000072a42e8a344eb66aca9ed13d5c633731cf54eeea1614610d365760405163332bf49d60e21b815260040160405180910390fd5b3660011981013560f01c9003601401358514610d685760405163e7ca808760e01b815260048101869052602401610558565b610d74868585856113e2565b9695505050505050565b3660011981013560f01c90033560601c610d99818484611114565b806001600160a01b0316836001600160a01b03167f70eb43c4a8ae8c40502dcf22436c509c28d6ff421cf07c491be56984bd9870688460405161081d91815260200190565b33610de76105e7565b6001600160a01b0316146104e75760405163118cdaa760e01b8152336004820152602401610558565b600042831015610e3657604051635c62004b60e11b815260048101849052602401610558565b60045460ff1615610e5a57604051630f3e8c1360e11b815260040160405180910390fd5b81158015610e6757508315155b15610e8557604051631a4778f160e31b815260040160405180910390fd5b6001546000610e92611057565b90506000610eb26000546003548460056111c2909392919063ffffffff16565b9050610ebe8184611854565b9250600083610edb3660011981013560f01c90033560601c610fd2565b610ee59190611841565b90506000610ef3878a611867565b9050818111610f025788610f0c565b610f0c878361187e565b95506000610f1a8888611867565b90508715801590610f29575080155b15610f4757604051634ef6878160e01b815260040160405180910390fd5b6000610f53898b611854565b60008990559050610f648288611854565b60025560038190556001879055610f7d60058787611314565b5060058a905560408051898152602081018c90529081018290527ff0b276e9ee40b3a3d065f636ee656c9bf1c9a0c4060fb212fd0861890c107be59060600160405180910390a1505050505050509392505050565b60006001600160a01b03821615611050576040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611027573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104b91906118a0565b610732565b4792915050565b6000600160085460ff16600281111561107257611072611815565b0361110e5760405163691d5cbd60e11b81523660011981013560f01c90036014013560048201526001600160a01b037f00000000000000000000000072a42e8a344eb66aca9ed13d5c633731cf54eeea169063d23ab97a90602401602060405180830381865afa1580156110ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050291906118a0565b50600090565b8060000361112157505050565b6001600160a01b0383166111a9576000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461117c576040519150601f19603f3d011682016040523d82523d6000602084013e611181565b606091505b50509050806111a357604051630df61d5560e01b815260040160405180910390fd5b50505050565b6111bd6001600160a01b0384168383611452565b505050565b6000816000036111d457506000611211565b845460004285106111e557426111e7565b845b90508181116111f757600061120c565b856112028383611841565b61120c9190611867565b925050505b949350505050565b6112216114b9565b61056a81611507565b6000806112378484611539565b87600101546112469190611854565b90508415611282576001600160a01b0386166000908152600288016020526040902054611273828761155d565b61127d9190611841565b611285565b60005b979650505050505050565b60008061129e888585611314565b905085156112da576001600160a01b03871660009081526002890160205260409020546112cb828861155d565b6112d59190611841565b6112dd565b60005b91506112e9818661155d565b6001600160a01b03909716600090815260029098016020525060409096209490945550929392505050565b6000806113218484611539565b8554909150421115611331574285555b8015611356578085600101600082825461134b9190611854565b9250508190556105bf565b846001015495945050505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6001546002546000919082841561140b5760005460035461140691600591886111c2565b61140e565b60005b905061141f60058989898986611290565b93508361142c8285611854565b6114369190611841565b6001556114438483611841565b60025550919695505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b1790526111bd908490611574565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166104e757604051631afcd79f60e31b815260040160405180910390fd5b61150f6114b9565b6001600160a01b03811661056157604051631e4fbdf760e01b815260006004820152602401610558565b600082156115545761154f83604084901b61187e565b6105e0565b60009392505050565b6000604061156b8484611867565b901c9392505050565b60006115896001600160a01b038416836115d7565b905080516000141580156115ae5750808060200190518101906115ac91906118b9565b155b156111bd57604051635274afe760e01b81526001600160a01b0384166004820152602401610558565b60606105e08383600084600080856001600160a01b031684866040516115fd91906118db565b60006040518083038185875af1925050503d806000811461163a576040519150601f19603f3d011682016040523d82523d6000602084013e61163f565b606091505b5091509150610d7486838360608261165a5761154f826116a1565b815115801561167157506001600160a01b0384163b155b1561169a57604051639996b31560e01b81526001600160a01b0385166004820152602401610558565b50806105e0565b8051156116b15780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b038116811461056a57600080fd5b600080600080600060a086880312156116f757600080fd5b8535611702816116ca565b97602087013597506040870135966060810135965060800135945092505050565b60008060006060848603121561173857600080fd5b505081359360208301359350604090920135919050565b60006020828403121561176157600080fd5b5035919050565b6000806040838503121561177b57600080fd5b50508035926020909101359150565b6000806040838503121561179d57600080fd5b82356117a8816116ca565b915060208301356117b8816116ca565b809150509250929050565b6000602082840312156117d557600080fd5b81356105e0816116ca565b6000806000606084860312156117f557600080fd5b8335611800816116ca565b95602085013595506040909401359392505050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156107325761073261182b565b808201808211156107325761073261182b565b80820281158282048414176107325761073261182b565b60008261189b57634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156118b257600080fd5b5051919050565b6000602082840312156118cb57600080fd5b815180151581146105e057600080fd5b6000825160005b818110156118fc57602081860181015185830152016118e2565b50600092019182525091905056fea2646970667358221220e776b0d407c54e3cd0385bb49b48a32ef4db0c3ad6a1e8458a82d995ef490ac064736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000072a42e8a344eb66aca9ed13d5c633731cf54eeea
-----Decoded View---------------
Arg [0] : caller (address): 0x72a42e8a344eB66ACA9eD13d5C633731cF54EeEa
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000072a42e8a344eb66aca9ed13d5c633731cf54eeea
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.