More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 1,122 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Approve | 21463643 | 20 hrs ago | IN | 0 ETH | 0.0001136 | ||||
Approve | 21463253 | 21 hrs ago | IN | 0 ETH | 0.00021109 | ||||
Approve | 21463193 | 21 hrs ago | IN | 0 ETH | 0.00018629 | ||||
Claim | 21451115 | 2 days ago | IN | 0 ETH | 0.00051382 | ||||
Claim | 21451108 | 2 days ago | IN | 0 ETH | 0.00064987 | ||||
Claim | 21450420 | 2 days ago | IN | 0 ETH | 0.00048548 | ||||
Approve | 21448744 | 2 days ago | IN | 0 ETH | 0.00032987 | ||||
Claim | 21445903 | 3 days ago | IN | 0 ETH | 0.00152088 | ||||
Approve | 21436209 | 4 days ago | IN | 0 ETH | 0.00065516 | ||||
Claim | 21421524 | 6 days ago | IN | 0 ETH | 0.00097698 | ||||
Approve | 21414354 | 7 days ago | IN | 0 ETH | 0.0005197 | ||||
Claim | 21413732 | 7 days ago | IN | 0 ETH | 0.00070473 | ||||
Approve | 21408888 | 8 days ago | IN | 0 ETH | 0.0002765 | ||||
Claim | 21408842 | 8 days ago | IN | 0 ETH | 0.00059707 | ||||
Approve | 21408829 | 8 days ago | IN | 0 ETH | 0.00045631 | ||||
Approve | 21405143 | 9 days ago | IN | 0 ETH | 0.00029813 | ||||
Approve | 21397511 | 10 days ago | IN | 0 ETH | 0.00052555 | ||||
Claim | 21397502 | 10 days ago | IN | 0 ETH | 0.00072196 | ||||
Approve | 21392234 | 10 days ago | IN | 0 ETH | 0.00049526 | ||||
Approve | 21390585 | 11 days ago | IN | 0 ETH | 0.00063819 | ||||
Approve | 21387895 | 11 days ago | IN | 0 ETH | 0.00118123 | ||||
Claim | 21387338 | 11 days ago | IN | 0 ETH | 0.00269765 | ||||
Claim | 21387303 | 11 days ago | IN | 0 ETH | 0.00218425 | ||||
Claim | 21386902 | 11 days ago | IN | 0 ETH | 0.00188154 | ||||
Approve | 21384122 | 11 days ago | IN | 0 ETH | 0.000607 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
18798139 | 373 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
FarmingPool
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IERC20, ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { SafeERC20 } from "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol"; import { IFarmingPool } from "./interfaces/IFarmingPool.sol"; import { FarmAccounting, FarmingLib } from "./FarmingLib.sol"; contract FarmingPool is IFarmingPool, Ownable, ERC20 { using SafeERC20 for IERC20; using Address for address payable; using FarmingLib for FarmingLib.Info; error SameStakingAndRewardsTokens(); error ZeroStakingTokenAddress(); error ZeroRewardsTokenAddress(); error ZeroDistributorAddress(); error SameDistributor(); error AccessDenied(); error InsufficientFunds(); error MaxBalanceExceeded(); uint256 internal constant _MAX_BALANCE = 1e32; IERC20 public immutable stakingToken; IERC20 public immutable rewardsToken; address private _distributor; FarmingLib.Data private _farm; modifier onlyDistributor { if (msg.sender != _distributor) revert AccessDenied(); _; } constructor(IERC20Metadata stakingToken_, IERC20 rewardsToken_) ERC20( string(abi.encodePacked("Farming of ", stakingToken_.name())), string(abi.encodePacked("farm", stakingToken_.symbol())) ) { if (stakingToken_ == rewardsToken_) revert SameStakingAndRewardsTokens(); if (address(stakingToken_) == address(0)) revert ZeroStakingTokenAddress(); if (address(rewardsToken_) == address(0)) revert ZeroRewardsTokenAddress(); stakingToken = stakingToken_; rewardsToken = rewardsToken_; } function decimals() public view virtual override returns (uint8) { return IERC20Metadata(address(stakingToken)).decimals(); } function farmInfo() public view returns(FarmAccounting.Info memory) { return _farm.farmInfo; } function distributor() public view virtual returns (address) { return _distributor; } function setDistributor(address distributor_) public virtual onlyOwner { if (distributor_ == address(0)) revert ZeroDistributorAddress(); address oldDistributor = _distributor; if (distributor_ == oldDistributor) revert SameDistributor(); emit DistributorChanged(oldDistributor, distributor_); _distributor = distributor_; } function startFarming(uint256 amount, uint256 period) public virtual onlyDistributor { uint256 reward = _makeInfo().startFarming(amount, period); emit RewardUpdated(reward, period); rewardsToken.safeTransferFrom(msg.sender, address(this), amount); } function stopFarming() public virtual onlyDistributor { uint256 leftover = _makeInfo().stopFarming(); emit RewardUpdated(0, 0); if (leftover > 0) { rewardsToken.safeTransfer(msg.sender, leftover); } } function farmed(address account) public view virtual returns (uint256) { return _makeInfo().farmed(account, balanceOf(account)); } function deposit(uint256 amount) public virtual { _mint(msg.sender, amount); if (balanceOf(msg.sender) > _MAX_BALANCE) revert MaxBalanceExceeded(); stakingToken.safeTransferFrom(msg.sender, address(this), amount); } function withdraw(uint256 amount) public virtual { _burn(msg.sender, amount); stakingToken.safeTransfer(msg.sender, amount); } function claim() public virtual { uint256 amount = _makeInfo().claim(msg.sender, balanceOf(msg.sender)); if (amount > 0) { _transferReward(rewardsToken, msg.sender, amount); } } function _transferReward(IERC20 reward, address to, uint256 amount) internal virtual { reward.safeTransfer(to, amount); } function exit() public virtual { withdraw(balanceOf(msg.sender)); claim(); } function rescueFunds(IERC20 token, uint256 amount) public virtual onlyDistributor { if (token == IERC20(address(0))) { payable(_distributor).sendValue(amount); } else { if (token == stakingToken) { if (stakingToken.balanceOf(address(this)) < totalSupply() + amount) revert InsufficientFunds(); } else if (token == rewardsToken) { if (rewardsToken.balanceOf(address(this)) < _farm.farmInfo.balance + amount) revert InsufficientFunds(); } token.safeTransfer(_distributor, amount); } } function _makeInfo() private view returns(FarmingLib.Info memory) { return FarmingLib.makeInfo(totalSupply, _farm); } // ERC20 overrides function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override { super._beforeTokenTransfer(from, to, amount); if (amount > 0 && from != to) { _makeInfo().updateBalances(from, to, amount); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.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. * * By default, the owner account will be the one that deploys the contract. 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 Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @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) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @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 { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer(address from, address to, uint256 amount) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @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, it is bubbled up by this * function (like regular Solidity function calls). * * 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. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @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`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol"; import "../interfaces/IDaiLikePermit.sol"; import "../interfaces/IPermit2.sol"; import "../interfaces/IWETH.sol"; import "../libraries/RevertReasonForwarder.sol"; /** * @title Implements efficient safe methods for ERC20 interface. * @notice Compared to the standard ERC20, this implementation offers several enhancements: * 1. more gas-efficient, providing significant savings in transaction costs. * 2. support for different permit implementations * 3. forceApprove functionality * 4. support for WETH deposit and withdraw */ library SafeERC20 { error SafeTransferFailed(); error SafeTransferFromFailed(); error ForceApproveFailed(); error SafeIncreaseAllowanceFailed(); error SafeDecreaseAllowanceFailed(); error SafePermitBadLength(); error Permit2TransferAmountTooHigh(); // Uniswap Permit2 address address private constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3; bytes4 private constant _PERMIT_LENGTH_ERROR = 0x68275857; // SafePermitBadLength.selector uint256 private constant _RAW_CALL_GAS_LIMIT = 5000; /** * @notice Fetches the balance of a specific ERC20 token held by an account. * Consumes less gas then regular `ERC20.balanceOf`. * @param token The IERC20 token contract for which the balance will be fetched. * @param account The address of the account whose token balance will be fetched. * @return tokenBalance The balance of the specified ERC20 token held by the account. */ function safeBalanceOf( IERC20 token, address account ) internal view returns(uint256 tokenBalance) { bytes4 selector = IERC20.balanceOf.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly mstore(0x00, selector) mstore(0x04, account) let success := staticcall(gas(), token, 0x00, 0x24, 0x00, 0x20) tokenBalance := mload(0) if or(iszero(success), lt(returndatasize(), 0x20)) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } } /** * @notice Attempts to safely transfer tokens from one address to another. * @dev If permit2 is true, uses the Permit2 standard; otherwise uses the standard ERC20 transferFrom. * Either requires `true` in return data, or requires target to be smart-contract and empty return data. * @param token The IERC20 token contract from which the tokens will be transferred. * @param from The address from which the tokens will be transferred. * @param to The address to which the tokens will be transferred. * @param amount The amount of tokens to transfer. * @param permit2 If true, uses the Permit2 standard for the transfer; otherwise uses the standard ERC20 transferFrom. */ function safeTransferFromUniversal( IERC20 token, address from, address to, uint256 amount, bool permit2 ) internal { if (permit2) { safeTransferFromPermit2(token, from, to, amount); } else { safeTransferFrom(token, from, to, amount); } } /** * @notice Attempts to safely transfer tokens from one address to another using the ERC20 standard. * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data. * @param token The IERC20 token contract from which the tokens will be transferred. * @param from The address from which the tokens will be transferred. * @param to The address to which the tokens will be transferred. * @param amount The amount of tokens to transfer. */ function safeTransferFrom( IERC20 token, address from, address to, uint256 amount ) internal { bytes4 selector = token.transferFrom.selector; bool success; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), from) mstore(add(data, 0x24), to) mstore(add(data, 0x44), amount) success := call(gas(), token, 0, data, 100, 0x0, 0x20) if success { switch returndatasize() case 0 { success := gt(extcodesize(token), 0) } default { success := and(gt(returndatasize(), 31), eq(mload(0), 1)) } } } if (!success) revert SafeTransferFromFailed(); } /** * @notice Attempts to safely transfer tokens from one address to another using the Permit2 standard. * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data. * @param token The IERC20 token contract from which the tokens will be transferred. * @param from The address from which the tokens will be transferred. * @param to The address to which the tokens will be transferred. * @param amount The amount of tokens to transfer. */ function safeTransferFromPermit2( IERC20 token, address from, address to, uint256 amount ) internal { if (amount > type(uint160).max) revert Permit2TransferAmountTooHigh(); bytes4 selector = IPermit2.transferFrom.selector; bool success; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), from) mstore(add(data, 0x24), to) mstore(add(data, 0x44), amount) mstore(add(data, 0x64), token) success := call(gas(), _PERMIT2, 0, data, 0x84, 0x0, 0x0) if success { success := gt(extcodesize(_PERMIT2), 0) } } if (!success) revert SafeTransferFromFailed(); } /** * @notice Attempts to safely transfer tokens to another address. * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data. * @param token The IERC20 token contract from which the tokens will be transferred. * @param to The address to which the tokens will be transferred. * @param value The amount of tokens to transfer. */ function safeTransfer( IERC20 token, address to, uint256 value ) internal { if (!_makeCall(token, token.transfer.selector, to, value)) { revert SafeTransferFailed(); } } /** * @notice Attempts to approve a spender to spend a certain amount of tokens. * @dev If `approve(from, to, amount)` fails, it tries to set the allowance to zero, and retries the `approve` call. * @param token The IERC20 token contract on which the call will be made. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. */ function forceApprove( IERC20 token, address spender, uint256 value ) internal { if (!_makeCall(token, token.approve.selector, spender, value)) { if ( !_makeCall(token, token.approve.selector, spender, 0) || !_makeCall(token, token.approve.selector, spender, value) ) { revert ForceApproveFailed(); } } } /** * @notice Safely increases the allowance of a spender. * @dev Increases with safe math check. Checks if the increased allowance will overflow, if yes, then it reverts the transaction. * Then uses `forceApprove` to increase the allowance. * @param token The IERC20 token contract on which the call will be made. * @param spender The address which will spend the funds. * @param value The amount of tokens to increase the allowance by. */ function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 allowance = token.allowance(address(this), spender); if (value > type(uint256).max - allowance) revert SafeIncreaseAllowanceFailed(); forceApprove(token, spender, allowance + value); } /** * @notice Safely decreases the allowance of a spender. * @dev Decreases with safe math check. Checks if the decreased allowance will underflow, if yes, then it reverts the transaction. * Then uses `forceApprove` to increase the allowance. * @param token The IERC20 token contract on which the call will be made. * @param spender The address which will spend the funds. * @param value The amount of tokens to decrease the allowance by. */ function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 allowance = token.allowance(address(this), spender); if (value > allowance) revert SafeDecreaseAllowanceFailed(); forceApprove(token, spender, allowance - value); } /** * @notice Attempts to execute the `permit` function on the provided token with the sender and contract as parameters. * Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2). * @dev Wraps `tryPermit` function and forwards revert reason if permit fails. * @param token The IERC20 token to execute the permit function on. * @param permit The permit data to be used in the function call. */ function safePermit(IERC20 token, bytes calldata permit) internal { if (!tryPermit(token, msg.sender, address(this), permit)) RevertReasonForwarder.reRevert(); } /** * @notice Attempts to execute the `permit` function on the provided token with custom owner and spender parameters. * Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2). * @dev Wraps `tryPermit` function and forwards revert reason if permit fails. * @param token The IERC20 token to execute the permit function on. * @param owner The owner of the tokens for which the permit is made. * @param spender The spender allowed to spend the tokens by the permit. * @param permit The permit data to be used in the function call. */ function safePermit(IERC20 token, address owner, address spender, bytes calldata permit) internal { if (!tryPermit(token, owner, spender, permit)) RevertReasonForwarder.reRevert(); } /** * @notice Attempts to execute the `permit` function on the provided token with the sender and contract as parameters. * @dev Invokes `tryPermit` with sender as owner and contract as spender. * @param token The IERC20 token to execute the permit function on. * @param permit The permit data to be used in the function call. * @return success Returns true if the permit function was successfully executed, false otherwise. */ function tryPermit(IERC20 token, bytes calldata permit) internal returns(bool success) { return tryPermit(token, msg.sender, address(this), permit); } /** * @notice The function attempts to call the permit function on a given ERC20 token. * @dev The function is designed to support a variety of permit functions, namely: IERC20Permit, IDaiLikePermit, and IPermit2. * It accommodates both Compact and Full formats of these permit types. * Please note, it is expected that the `expiration` parameter for the compact Permit2 and the `deadline` parameter * for the compact Permit are to be incremented by one before invoking this function. This approach is motivated by * gas efficiency considerations; as the unlimited expiration period is likely to be the most common scenario, and * zeros are cheaper to pass in terms of gas cost. Thus, callers should increment the expiration or deadline by one * before invocation for optimized performance. * @param token The address of the ERC20 token on which to call the permit function. * @param owner The owner of the tokens. This address should have signed the off-chain permit. * @param spender The address which will be approved for transfer of tokens. * @param permit The off-chain permit data, containing different fields depending on the type of permit function. * @return success A boolean indicating whether the permit call was successful. */ function tryPermit(IERC20 token, address owner, address spender, bytes calldata permit) internal returns(bool success) { // load function selectors for different permit standards bytes4 permitSelector = IERC20Permit.permit.selector; bytes4 daiPermitSelector = IDaiLikePermit.permit.selector; bytes4 permit2Selector = IPermit2.permit.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let ptr := mload(0x40) // Switch case for different permit lengths, indicating different permit standards switch permit.length // Compact IERC20Permit case 100 { mstore(ptr, permitSelector) // store selector mstore(add(ptr, 0x04), owner) // store owner mstore(add(ptr, 0x24), spender) // store spender // Compact IERC20Permit.permit(uint256 value, uint32 deadline, uint256 r, uint256 vs) { // stack too deep let deadline := shr(224, calldataload(add(permit.offset, 0x20))) // loads permit.offset 0x20..0x23 let vs := calldataload(add(permit.offset, 0x44)) // loads permit.offset 0x44..0x63 calldatacopy(add(ptr, 0x44), permit.offset, 0x20) // store value = copy permit.offset 0x00..0x19 mstore(add(ptr, 0x64), sub(deadline, 1)) // store deadline = deadline - 1 mstore(add(ptr, 0x84), add(27, shr(255, vs))) // store v = most significant bit of vs + 27 (27 or 28) calldatacopy(add(ptr, 0xa4), add(permit.offset, 0x24), 0x20) // store r = copy permit.offset 0x24..0x43 mstore(add(ptr, 0xc4), shr(1, shl(1, vs))) // store s = vs without most significant bit } // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0xe4, 0, 0) } // Compact IDaiLikePermit case 72 { mstore(ptr, daiPermitSelector) // store selector mstore(add(ptr, 0x04), owner) // store owner mstore(add(ptr, 0x24), spender) // store spender // Compact IDaiLikePermit.permit(uint32 nonce, uint32 expiry, uint256 r, uint256 vs) { // stack too deep let expiry := shr(224, calldataload(add(permit.offset, 0x04))) // loads permit.offset 0x04..0x07 let vs := calldataload(add(permit.offset, 0x28)) // loads permit.offset 0x28..0x47 mstore(add(ptr, 0x44), shr(224, calldataload(permit.offset))) // store nonce = copy permit.offset 0x00..0x03 mstore(add(ptr, 0x64), sub(expiry, 1)) // store expiry = expiry - 1 mstore(add(ptr, 0x84), true) // store allowed = true mstore(add(ptr, 0xa4), add(27, shr(255, vs))) // store v = most significant bit of vs + 27 (27 or 28) calldatacopy(add(ptr, 0xc4), add(permit.offset, 0x08), 0x20) // store r = copy permit.offset 0x08..0x27 mstore(add(ptr, 0xe4), shr(1, shl(1, vs))) // store s = vs without most significant bit } // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0x104, 0, 0) } // IERC20Permit case 224 { mstore(ptr, permitSelector) calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0xe4, 0, 0) } // IDaiLikePermit case 256 { mstore(ptr, daiPermitSelector) calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0x104, 0, 0) } // Compact IPermit2 case 96 { // Compact IPermit2.permit(uint160 amount, uint32 expiration, uint32 nonce, uint32 sigDeadline, uint256 r, uint256 vs) mstore(ptr, permit2Selector) // store selector mstore(add(ptr, 0x04), owner) // store owner mstore(add(ptr, 0x24), token) // store token calldatacopy(add(ptr, 0x50), permit.offset, 0x14) // store amount = copy permit.offset 0x00..0x13 // and(0xffffffffffff, ...) - conversion to uint48 mstore(add(ptr, 0x64), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x14))), 1))) // store expiration = ((permit.offset 0x14..0x17 - 1) & 0xffffffffffff) mstore(add(ptr, 0x84), shr(224, calldataload(add(permit.offset, 0x18)))) // store nonce = copy permit.offset 0x18..0x1b mstore(add(ptr, 0xa4), spender) // store spender // and(0xffffffffffff, ...) - conversion to uint48 mstore(add(ptr, 0xc4), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x1c))), 1))) // store sigDeadline = ((permit.offset 0x1c..0x1f - 1) & 0xffffffffffff) mstore(add(ptr, 0xe4), 0x100) // store offset = 256 mstore(add(ptr, 0x104), 0x40) // store length = 64 calldatacopy(add(ptr, 0x124), add(permit.offset, 0x20), 0x20) // store r = copy permit.offset 0x20..0x3f calldatacopy(add(ptr, 0x144), add(permit.offset, 0x40), 0x20) // store vs = copy permit.offset 0x40..0x5f // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature) success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0) } // IPermit2 case 352 { mstore(ptr, permit2Selector) calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature) success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0) } // Unknown default { mstore(ptr, _PERMIT_LENGTH_ERROR) revert(ptr, 4) } } } /** * @dev Executes a low level call to a token contract, making it resistant to reversion and erroneous boolean returns. * @param token The IERC20 token contract on which the call will be made. * @param selector The function signature that is to be called on the token contract. * @param to The address to which the token amount will be transferred. * @param amount The token amount to be transferred. * @return success A boolean indicating if the call was successful. Returns 'true' on success and 'false' on failure. * In case of success but no returned data, validates that the contract code exists. * In case of returned data, ensures that it's a boolean `true`. */ function _makeCall( IERC20 token, bytes4 selector, address to, uint256 amount ) private returns (bool success) { assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), to) mstore(add(data, 0x24), amount) success := call(gas(), token, 0, data, 0x44, 0x0, 0x20) if success { switch returndatasize() case 0 { success := gt(extcodesize(token), 0) } default { success := and(gt(returndatasize(), 31), eq(mload(0), 1)) } } } } /** * @notice Safely deposits a specified amount of Ether into the IWETH contract. Consumes less gas then regular `IWETH.deposit`. * @param weth The IWETH token contract. * @param amount The amount of Ether to deposit into the IWETH contract. */ function safeDeposit(IWETH weth, uint256 amount) internal { if (amount > 0) { bytes4 selector = IWETH.deposit.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly mstore(0, selector) if iszero(call(gas(), weth, amount, 0, 4, 0, 0)) { returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) } } } } /** * @notice Safely withdraws a specified amount of wrapped Ether from the IWETH contract. Consumes less gas then regular `IWETH.withdraw`. * @dev Uses inline assembly to interact with the IWETH contract. * @param weth The IWETH token contract. * @param amount The amount of wrapped Ether to withdraw from the IWETH contract. */ function safeWithdraw(IWETH weth, uint256 amount) internal { bytes4 selector = IWETH.withdraw.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly mstore(0, selector) mstore(4, amount) if iszero(call(gas(), weth, 0, 0, 0x24, 0, 0)) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } } /** * @notice Safely withdraws a specified amount of wrapped Ether from the IWETH contract to a specified recipient. * Consumes less gas then regular `IWETH.withdraw`. * @param weth The IWETH token contract. * @param amount The amount of wrapped Ether to withdraw from the IWETH contract. * @param to The recipient of the withdrawn Ether. */ function safeWithdrawTo(IWETH weth, uint256 amount, address to) internal { safeWithdraw(weth, amount); if (to != address(this)) { assembly ("memory-safe") { // solhint-disable-line no-inline-assembly if iszero(call(_RAW_CALL_GAS_LIMIT, to, amount, 0, 0, 0, 0)) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { FarmAccounting } from "../accounting/FarmAccounting.sol"; interface IFarmingPool is IERC20 { event DistributorChanged(address oldDistributor, address newDistributor); event RewardUpdated(uint256 reward, uint256 duration); // View functions function distributor() external view returns(address); function farmInfo() external view returns(FarmAccounting.Info memory); function farmed(address account) external view returns(uint256); // User functions function deposit(uint256 amount) external; function withdraw(uint256 amount) external; function claim() external; function exit() external; // Owner functions function setDistributor(address distributor_) external; // Distributor functions function startFarming(uint256 amount, uint256 period) external; function rescueFunds(IERC20 token, uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { FarmAccounting } from "./accounting/FarmAccounting.sol"; import { UserAccounting } from "./accounting/UserAccounting.sol"; /// @title FarmingLib /// @dev A library for farming logic, using FarmAccounting and UserAccounting. library FarmingLib { using FarmAccounting for FarmAccounting.Info; using UserAccounting for UserAccounting.Info; using FarmingLib for FarmingLib.Info; /// @dev Struct containing farm and user detailed info for farming operations. See {FarmAccounting.Info} and {UserAccounting.Info} for. struct Data { FarmAccounting.Info farmInfo; UserAccounting.Info userInfo; } /// @dev Struct containing the total supply function and a data slot for EVM storage. struct Info { function() internal view returns(uint256) getTotalSupply; bytes32 dataSlot; } /** * @notice Creates a new Info struct. * @param getTotalSupply The function to get the total supply. * @param data The data struct for storage. * @return info The created Info struct. */ function makeInfo(function() internal view returns(uint256) getTotalSupply, Data storage data) internal pure returns(Info memory info) { info.getTotalSupply = getTotalSupply; bytes32 dataSlot; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly dataSlot := data.slot } info.dataSlot = dataSlot; } /** * @notice Retrieves the Data struct from an Info struct. * @param self The Info struct. * @return data The retrieved Data struct. */ function getData(Info memory self) internal pure returns(Data storage data) { bytes32 dataSlot = self.dataSlot; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly data.slot := dataSlot } } /** * @notice Begins farming for a specified period. * @param self The Info struct. * @param amount The amount to farm. * @param period The farming period. * @return reward The farming reward. */ function startFarming(Info memory self, uint256 amount, uint256 period) internal returns(uint256 reward) { Data storage data = self.getData(); data.userInfo.updateFarmedPerToken(_farmedPerToken(self)); reward = data.farmInfo.startFarming(amount, period); } /** * @notice Stops farming immediately. * @param self The FarmingLib.Info struct to retrieve data from storage. * @return leftover Amount of reward tokens remaining after farming. */ function stopFarming(Info memory self) internal returns(uint256 leftover) { Data storage data = self.getData(); data.userInfo.updateFarmedPerToken(_farmedPerToken(self)); leftover = data.farmInfo.stopFarming(); } /** * @notice Gets the farmed amount for an account. * @param self The Info struct. * @param account The account to check. * @param balance The account balance. * @return result The farmed amount. */ function farmed(Info memory self, address account, uint256 balance) internal view returns(uint256) { return self.getData().userInfo.farmed(account, balance, _farmedPerToken(self)); } /** * @notice Claims the farmed amount for an account. * @param self The Info struct. * @param account The account to claim for. * @param balance The account balance. * @return amount The claimed amount. */ function claim(Info memory self, address account, uint256 balance) internal returns(uint256 amount) { Data storage data = self.getData(); uint256 fpt = _farmedPerToken(self); amount = data.userInfo.farmed(account, balance, fpt); if (amount > 0) { data.userInfo.eraseFarmed(account, balance, fpt); data.farmInfo.claim(amount); } } /** * @notice Updates the balances of two accounts. * @param self The Info struct. * @param from The account to transfer from. * @param to The account to transfer to. * @param amount The amount to transfer. */ function updateBalances(Info memory self, address from, address to, uint256 amount) internal { self.getData().userInfo.updateBalances(from, to, amount, _farmedPerToken(self)); } function _farmedPerToken(Info memory self) private view returns (uint256) { return self.getData().userInfo.farmedPerToken(_infoToContext(self), _lazyGetSupply, _lazyGetFarmed); } // UserAccounting bindings function _lazyGetSupply(bytes32 context) private view returns(uint256) { Info memory self = _contextToInfo(context); return self.getTotalSupply(); } function _lazyGetFarmed(bytes32 context, uint256 checkpoint) private view returns(uint256) { Info memory self = _contextToInfo(context); return self.getData().farmInfo.farmedSinceCheckpointScaled(checkpoint); } function _contextToInfo(bytes32 context) private pure returns(Info memory self) { assembly ("memory-safe") { // solhint-disable-line no-inline-assembly self := context } } function _infoToContext(Info memory self) private pure returns(bytes32 context) { assembly ("memory-safe") { // solhint-disable-line no-inline-assembly context := self } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @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 Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @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 amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` 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 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; // EIP-2612 is Final as of 2022-11-01. This file is deprecated. import "./IERC20Permit.sol";
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IDaiLikePermit { function permit( address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IPermit2 { struct PermitDetails { // ERC20 token address address token; // the maximum amount allowed to spend uint160 amount; // timestamp at which a spender's token allowances become invalid uint48 expiration; // an incrementing value indexed per owner,token,and spender for each signature uint48 nonce; } /// @notice The permit message signed for a single token allownce struct PermitSingle { // the permit data for a single token alownce PermitDetails details; // address permissioned on the allowed tokens address spender; // deadline on the permit signature uint256 sigDeadline; } /// @notice Packed allowance struct PackedAllowance { // amount allowed uint160 amount; // permission expiry uint48 expiration; // an incrementing value indexed per owner,token,and spender for each signature uint48 nonce; } function transferFrom(address user, address spender, uint160 amount, address token) external; function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external; function allowance(address user, address token, address spender) external view returns (PackedAllowance memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IWETH is IERC20 { event Deposit(address indexed dst, uint wad); event Withdrawal(address indexed src, uint wad); function deposit() external payable; function withdraw(uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Revert reason forwarder. library RevertReasonForwarder { /// @dev Forwards latest externall call revert. function reRevert() internal pure { // bubble up revert reason from latest external call assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; library FarmAccounting { error ZeroDuration(); error DurationTooLarge(); error AmountTooLarge(); struct Info { uint40 finished; uint32 duration; uint184 reward; uint256 balance; } uint256 internal constant _MAX_REWARD_AMOUNT = 1e32; // 108 bits uint256 internal constant _SCALE = 1e18; // 60 bits /// @dev Requires extra 18 decimals for precision, result fits in 168 bits function farmedSinceCheckpointScaled(Info storage info, uint256 checkpoint) internal view returns(uint256 amount) { unchecked { (uint40 finished, uint32 duration, uint184 reward) = (info.finished, info.duration, info.reward); if (duration > 0) { uint256 elapsed = Math.min(block.timestamp, finished) - Math.min(checkpoint, finished); // size of (type(uint32).max * _MAX_REWARD_AMOUNT * _SCALE) is less than 200 bits, so there is no overflow return elapsed * reward * _SCALE / duration; } } } function startFarming(Info storage info, uint256 amount, uint256 period) internal returns(uint256) { if (period == 0) revert ZeroDuration(); if (period > type(uint32).max) revert DurationTooLarge(); // If something left from prev farming add it to the new farming (uint40 finished, uint32 duration, uint184 reward, uint256 balance) = (info.finished, info.duration, info.reward, info.balance); if (block.timestamp < finished) { amount += reward - farmedSinceCheckpointScaled(info, finished - duration) / _SCALE; } if (amount > _MAX_REWARD_AMOUNT) revert AmountTooLarge(); (info.finished, info.duration, info.reward, info.balance) = ( uint40(block.timestamp + period), uint32(period), uint184(amount), balance + amount ); return amount; } function stopFarming(Info storage info) internal returns(uint256 leftover) { leftover = info.reward - farmedSinceCheckpointScaled(info, info.finished - info.duration) / _SCALE; (info.finished, info.duration, info.reward, info.balance) = ( uint40(block.timestamp), uint32(0), uint184(0), info.balance - leftover ); } function claim(Info storage info, uint256 amount) internal { info.balance -= amount; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { FarmAccounting } from "./FarmAccounting.sol"; library UserAccounting { struct Info { uint40 checkpoint; uint216 farmedPerTokenStored; mapping(address => int256) corrections; } function farmedPerToken( Info storage info, bytes32 context, function(bytes32) internal view returns(uint256) lazyGetSupply, function(bytes32, uint256) internal view returns(uint256) lazyGetFarmed ) internal view returns(uint256) { (uint256 checkpoint, uint256 fpt) = (info.checkpoint, info.farmedPerTokenStored); if (block.timestamp != checkpoint) { uint256 supply = lazyGetSupply(context); if (supply > 0) { // fpt increases by 168 bit / supply unchecked { fpt += lazyGetFarmed(context, checkpoint) / supply; } } } return fpt; } function farmed(Info storage info, address account, uint256 balance, uint256 fpt) internal view returns(uint256) { // balance * fpt is less than 168 bit return uint256(int256(balance * fpt) - info.corrections[account]) / FarmAccounting._SCALE; } function eraseFarmed(Info storage info, address account, uint256 balance, uint256 fpt) internal { // balance * fpt is less than 168 bit info.corrections[account] = int256(balance * fpt); } function updateFarmedPerToken(Info storage info, uint256 fpt) internal { (info.checkpoint, info.farmedPerTokenStored) = (uint40(block.timestamp), uint216(fpt)); } function updateBalances(Info storage info, address from, address to, uint256 amount, uint256 fpt) internal { bool fromZero = (from == address(0)); bool toZero = (to == address(0)); if (amount > 0 && from != to) { if (fromZero || toZero) { updateFarmedPerToken(info, fpt); } // fpt is less than 168 bit, so amount should be less 98 bit int256 diff = int256(amount * fpt); if (!fromZero) { info.corrections[from] -= diff; } if (!toZero) { info.corrections[to] += diff; } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @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. */ 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]. */ 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 v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
{ "remappings": [ "@1inch/=node_modules/@1inch/", "@chainlink/=node_modules/@chainlink/", "@eth-optimism/=node_modules/@eth-optimism/", "@gearbox-protocol/=node_modules/@gearbox-protocol/", "@openzeppelin/=node_modules/@openzeppelin/", "@redstone-finance/=node_modules/@redstone-finance/", "ds-test/=lib/forge-std/lib/ds-test/src/", "eth-gas-reporter/=node_modules/eth-gas-reporter/", "forge-std/=lib/forge-std/src/" ], "optimizer": { "enabled": true, "runs": 1000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IERC20Metadata","name":"stakingToken_","type":"address"},{"internalType":"contract IERC20","name":"rewardsToken_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessDenied","type":"error"},{"inputs":[],"name":"AmountTooLarge","type":"error"},{"inputs":[],"name":"DurationTooLarge","type":"error"},{"inputs":[],"name":"InsufficientFunds","type":"error"},{"inputs":[],"name":"MaxBalanceExceeded","type":"error"},{"inputs":[],"name":"SafeTransferFailed","type":"error"},{"inputs":[],"name":"SafeTransferFromFailed","type":"error"},{"inputs":[],"name":"SameDistributor","type":"error"},{"inputs":[],"name":"SameStakingAndRewardsTokens","type":"error"},{"inputs":[],"name":"ZeroDistributorAddress","type":"error"},{"inputs":[],"name":"ZeroDuration","type":"error"},{"inputs":[],"name":"ZeroRewardsTokenAddress","type":"error"},{"inputs":[],"name":"ZeroStakingTokenAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldDistributor","type":"address"},{"indexed":false,"internalType":"address","name":"newDistributor","type":"address"}],"name":"DistributorChanged","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":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"RewardUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"distributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"farmInfo","outputs":[{"components":[{"internalType":"uint40","name":"finished","type":"uint40"},{"internalType":"uint32","name":"duration","type":"uint32"},{"internalType":"uint184","name":"reward","type":"uint184"},{"internalType":"uint256","name":"balance","type":"uint256"}],"internalType":"struct FarmAccounting.Info","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"farmed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardsToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"distributor_","type":"address"}],"name":"setDistributor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"name":"startFarming","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopFarming","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c060409080825234620004eb578181620023db8038038091620000248285620004f0565b833981010312620004eb5780516001600160a01b039182821691829003620004eb576020809101519280841690818503620004eb5785516306fdde0360e01b815260049390600090818187818a5afa908115620004e1578291620004c3575b50620000c6602b8a5180936a02330b936b4b7339037b3160ad1b87830152620000b5815180928986860191016200052a565b810103600b810184520182620004f0565b88516395d89b4160e01b815293828588818b5afa948515620004b957839562000490575b50895190636661726d60e01b858301526200012886519683886200011860249a8b948b86860191016200052a565b8101038a810185520183620004f0565b8354336001600160a01b031982168117865591167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08580a381516001600160401b03939091908483116200039e578854926001948585811c9516801562000485575b8886101462000473578190601f9586811162000420575b508890868311600114620003bc578492620003b0575b5050600019600383901b1c191690851b1789555b81519485116200039e576005968754908582811c9216801562000393575b888310146200038257508381116200033c575b5085928511600114620002d5579394508492919083620002c9575b50501b916000199060031b1c19161790555b808314620002ba578215620002ab57156200029d575060805260a05251611e179081620005c482396080518181816103bd0152818161086801528181610afe01528181610ed90152611532015260a0518181816102d30152818161094601528181610ce1015281816111d401526116ff0152f35b83516330c1035b60e21b8152fd5b508351633bbbfc7960e01b8152fd5b508351630d21e9d760e41b8152fd5b01519250388062000217565b86815285812093958591601f198316915b8883831062000321575050501062000307575b505050811b01905562000229565b015160001960f88460031b161c19169055388080620002f9565b858701518855909601959485019487935090810190620002e6565b878252868220848088018a1c82019289891062000378575b01891c019085905b8281106200036c575050620001fc565b8381550185906200035c565b9250819262000354565b634e487b7160e01b835260228b5282fd5b91607f1691620001e9565b634e487b7160e01b8152604189528690fd5b015190503880620001b7565b8c85528985208894509190601f198416865b8c828210620004095750508411620003ef575b505050811b018955620001cb565b015160001960f88460031b161c19169055388080620003e1565b8385015186558b97909501949384019301620003ce565b9091508b84528884208680850160051c8201928b861062000469575b918991869594930160051c01915b8281106200045a575050620001a1565b8681558594508991016200044a565b925081926200043c565b634e487b7160e01b835260228b528883fd5b94607f16946200018a565b620004b19195503d8085833e620004a88183620004f0565b8101906200054f565b9338620000ea565b8a513d85823e3d90fd5b620004da91503d8084833e620004a88183620004f0565b3862000083565b89513d84823e3d90fd5b600080fd5b601f909101601f19168101906001600160401b038211908210176200051457604052565b634e487b7160e01b600052604160045260246000fd5b60005b8381106200053e5750506000910152565b81810151838201526020016200052d565b602081830312620004eb5780516001600160401b0391828211620004eb57019082601f83011215620004eb5781519081116200051457604051926200059f601f8301601f191660200185620004f0565b81845260208284010111620004eb57620005c091602080850191016200052a565b9056fe6080604081815260048036101561001557600080fd5b600092833560e01c90816306fdde031461124f57508063095ea7b31461122557806318160ddd146112065780631bfa4c04146110ef5780631d49d66c1461104b57806323b872dd14610f805780632e1a7d4d14610f63578063313ce56714610e935780633950935114610e445780634216f97214610de95780634e71d92d14610dd05780637026122214610bbf57806370a0823114610b88578063715018a614610b2257806372f702f314610ade57806375619ab5146109fd57806378e3214f146107035780638da5cb5b146106dd57806395d89b41146105db578063a457c2d71461051b578063a9059cbb146104ea578063b6b55f251461031f578063bfe10928146102f7578063d1af0c7d146102b3578063dd62ed3e1461026a578063e9fad8ee146102355763f2fde38b1461014c57600080fd5b346102315760203660031901126102315761016561138c565b9061016e6119e9565b6001600160a01b038092169283156101c857505082548273ffffffffffffffffffffffffffffffffffffffff198216178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b906020608492519162461bcd60e51b8352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b8280fd5b50503461026657816003193601126102665761025b9033835260016020528220546114b7565b6102636116af565b80f35b5080fd5b5050346102665780600319360112610266578060209261028861138c565b6102906113a7565b6001600160a01b0391821683526002865283832091168252845220549051908152f35b505034610266578160031936011261026657602090516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b5050346102665781600319360112610266576020906001600160a01b03600654169051908152f35b503461023157602091826003193601126104e65781359233156104a557831515808061049d575b610407575b5060019061035b85600354611756565b6003553386528181528286208581540190558251858152867fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef833393a3338652526d04ee2d6d415b85acef810000000081852054116103e157836102638430337f00000000000000000000000000000000000000000000000000000000000000006118ae565b517f24691f6b000000000000000000000000000000000000000000000000000000008152fd5b61040f611779565b9061041d8383015192611411565b9080610495575b61042f575b5061034b565b4264ffffffffff16602882901b64ffffffffff19161760028301556003906104579087611848565b9133885201825282862080548783820193841291129080158216911516176104825755600138610429565b602487601187634e487b7160e01b835252fd5b506001610424565b506001610346565b60649291519162461bcd60e51b8352820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152fd5b8380fd5b50503461026657806003193601126102665760209061051461050a61138c565b6024359033611a41565b5160018152f35b5082346105d857826003193601126105d85761053561138c565b91836024359233815260026020528181206001600160a01b038616825260205220549082821061056f576020856105148585038733611cad565b608490602086519162461bcd60e51b8352820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152fd5b80fd5b509034610231578260031936011261023157805191836005549060019082821c9282811680156106d3575b60209586861082146106c0575084885290811561069e5750600114610645575b6106418686610637828b03836113ef565b5191829182611343565b0390f35b929550600583527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b82841061068b575050508261064194610637928201019438610626565b805486850188015292860192810161066e565b60ff191687860152505050151560051b83010192506106378261064138610626565b836022602492634e487b7160e01b835252fd5b93607f1693610606565b5050346102665781600319360112610266576001600160a01b0360209254169051908152f35b5090346102315780600319360112610231576001600160a01b038235818116929183820361092c576024938435928260065416918233036109ee578061085c575050506006541681471061081a578580809381935af13d15610815573d67ffffffffffffffff811161080357825190610786601f8201601f1916602001836113ef565b81528560203d92013e5b1561079b5750505080f35b608492916020603a92519362461bcd60e51b85528401528201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152fd5b8386604187634e487b7160e01b835252fd5b610790565b606485601d86602087519362461bcd60e51b85528401528201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152fd5b909395919492809897987f000000000000000000000000000000000000000000000000000000000000000016908183146000146109425750602091508351928380926370a0823160e01b8252308c8301525afa908115610938578691610903575b506108ca85600354611756565b116108db575061026393945061194f565b8590517f356680b7000000000000000000000000000000000000000000000000000000008152fd5b90506020813d8211610930575b8161091d602093836113ef565b8101031261092c5751386108bd565b8580fd5b3d9150610910565b82513d88823e3d90fd5b90507f00000000000000000000000000000000000000000000000000000000000000001680911461097c575b50505061026393945061194f565b6020908351928380926370a0823160e01b8252308c8301525afa9081156109385786916109bd575b506109b185600854611756565b116108db57808061096e565b90506020813d82116109e6575b816109d7602093836113ef565b8101031261092c5751386109a4565b3d91506109ca565b878651634ca8886760e01b8152fd5b50903461023157602036600319011261023157610a1861138c565b90610a216119e9565b6001600160a01b03809216928315610ab75760065492831690818514610a905750817fa9f739537fc57540bed0a44e33e27baa63290d865cc15f0f16cf17d38c998a4d9173ffffffffffffffffffffffffffffffffffffffff19949351908152856020820152a1161760065580f35b82517f8750ee90000000000000000000000000000000000000000000000000000000008152fd5b90517f71702079000000000000000000000000000000000000000000000000000000008152fd5b505034610266578160031936011261026657602090516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b83346105d857806003193601126105d857610b3b6119e9565b806001600160a01b03815473ffffffffffffffffffffffffffffffffffffffff1981168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50503461026657602036600319011261026657806020926001600160a01b03610baf61138c565b1681526001845220549051908152f35b5090346102315780600319360112610231578135916024356001600160a01b03600654163303610dc157610bf1611779565b610c20610c02602083015192611411565b4264ffffffffff1660289190911b64ffffffffff1916176002830155565b84928215610d9a5763ffffffff90818411610d735782549064ffffffffff90818316926001860193845495814210610d2c575b5050506d04ee2d6d415b85acef81000000008711610d05575091859391610cad7f3efe2b1ade87153c913a322f09a35c930d7fd699770b8d7cdd294e1debf6e9e4978795610ca66102639c9b9942611756565b1693611756565b905568ffffffffffffffffff198460481b1668ffffffff00000000008460281b161717905582519182526020820152a130337f00000000000000000000000000000000000000000000000000000000000000006118ae565b87517f06250401000000000000000000000000000000000000000000000000000000008152fd5b610d6a939950610d5a85610d538594670de0b6b3a764000094610d649760281c1690611824565b16896117b8565b049060481c61183b565b89611756565b95388080610c53565b85517f426a1073000000000000000000000000000000000000000000000000000000008152fd5b84517f68d5686e000000000000000000000000000000000000000000000000000000008152fd5b509051634ca8886760e01b8152fd5b83346105d857806003193601126105d8576102636116af565b50503461026657602036600319011261026657610e3d602092610e0a61138c565b83610e13611779565b926001600160a01b038316815260018752205490610e376002878501510193611411565b92611874565b9051908152f35b505034610266578060031936011261026657610514602092610e8c610e6761138c565b91338152600286528481206001600160a01b0384168252865284602435912054611756565b9033611cad565b5091346105d857806003193601126105d8576020825180947f313ce567000000000000000000000000000000000000000000000000000000008252816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa928315610f57578193610f16575b60208460ff855191168152f35b9092506020813d8211610f4f575b81610f31602093836113ef565b8101031261023157519160ff831683036105d8575060ff6020610f09565b3d9150610f24565b509051903d90823e3d90fd5b8382346102665760203660031901126102665761026390356114b7565b5082903461026657606036600319011261026657610f9c61138c565b610fa46113a7565b9184604435946001600160a01b038416815260026020528181203382526020522054906000198203610fdf575b602086610514878787611a41565b8482106110085750918391610ffd6020969561051495033383611cad565b919394819350610fd1565b606490602087519162461bcd60e51b8352820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152fd5b5050346102665781600319360112610266576080916060825161106d816113bd565b828152826020820152828482015201528051611088816113bd565b6007549176ffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff8416938484526020840163ffffffff90818360281c1681528486019260481c835260606008549601958652845196875251166020860152511690830152516060820152f35b50346102315782600319360112610231576001600160a01b036006541633036111f857507f3efe2b1ade87153c913a322f09a35c930d7fd699770b8d7cdd294e1debf6e9e461113c611779565b9161116c61114e602085015194611411565b4264ffffffffff1660289190911b64ffffffffff1916176002850155565b8254926111a264ffffffffff94670de0b6b3a7640000610d5a8761119b63ffffffff8560281c16828616611824565b16856117b8565b93600182016111b286825461183b565b9055421690558051848152846020820152a1806111cd575080f35b61026390337f000000000000000000000000000000000000000000000000000000000000000061194f565b9051634ca8886760e01b8152fd5b5050346102665781600319360112610266576020906003549051908152f35b50503461026657806003193601126102665760209061051461124561138c565b6024359033611cad565b90508284346105d857806003193601126105d857809380549160019083821c92828516948515611339575b60209586861081146113265785895290811561130257506001146112aa575b6106418787610637828c03836113ef565b81529295507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8284106112ef57505050826106419461063792820101948680611299565b80548685018801529286019281016112d1565b60ff19168887015250505050151560051b8301019250610637826106418680611299565b602484602285634e487b7160e01b835252fd5b93607f169361127a565b6020808252825181830181905290939260005b82811061137857505060409293506000838284010152601f8019910116010190565b818101860151848201604001528501611356565b600435906001600160a01b03821682036113a257565b600080fd5b602435906001600160a01b03821682036113a257565b6080810190811067ffffffffffffffff8211176113d957604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176113d957604052565b602081016002815101549064ffffffffff82169160281c92824203611437575b50505090565b61143f61148d565b505160031461145e57634e487b7160e01b600052605160045260246000fd5b600354908115611431576114849261147f9161147861148d565b50516117b8565b611798565b01388080611431565b604051906040820182811067ffffffffffffffff8211176113d95760405260006020838281520152565b331561164557801515808061163d575b6115c2575b503360005260016020526040600020549080821061155857806115569233600052600160205203604060002055806003540360035560006040518281527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60203392a3337f000000000000000000000000000000000000000000000000000000000000000061194f565b565b608460405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152fd5b6115ca611779565b906115d9602083015192611411565b9080611635575b6115eb575b506114cc565b4264ffffffffff16602882901b64ffffffffff19161760028301556003906116139084611848565b91336000520160205261162c604060002091825461185b565b905538806115e5565b5060016115e0565b5060016114c7565b608460405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152fd5b6116b7611779565b3360005260016020526040600020546116d4602083015192611411565b6116e381833360028701611874565b928315159283611723575b5050506116f85750565b61155690337f000000000000000000000000000000000000000000000000000000000000000061194f565b60019261172f91611848565b33600052600382016020526040600020550161174c83825461183b565b90553880806116ee565b9190820180921161176357565b634e487b7160e01b600052601160045260246000fd5b61178161148d565b5061178a61148d565b600381526007602082015290565b81156117a2570490565b634e487b7160e01b600052601260045260246000fd5b91906000925464ffffffffff81169063ffffffff8160281c1692836117dd5750505050565b61181394955090670de0b6b3a7640000929182421060001461181e5742925b808210156118165750905b60481c91030202611798565b90565b905090611807565b826117fc565b64ffffffffff918216908216039190821161176357565b9190820391821161176357565b8181029291811591840414171561176357565b8181039291600013801582851316918412161761176357565b6001906001600160a01b03611895670de0b6b3a7640000966118aa96611848565b9316600052016020526040600020549061185b565b0490565b9260209291606491600093604051927f23b872dd00000000000000000000000000000000000000000000000000000000845260048401526024830152604482015282855af1908161192c575b501561190257565b60046040517ff4059071000000000000000000000000000000000000000000000000000000008152fd5b90503d156119475750600160005114601f3d11165b386118fa565b3b1515611941565b916044602092600092604051917fa9059cbb0000000000000000000000000000000000000000000000000000000083526004830152602482015282855af190816119c6575b501561199c57565b60046040517ffb7f5079000000000000000000000000000000000000000000000000000000008152fd5b90503d156119e15750600160005114601f3d11165b38611994565b3b15156119db565b6001600160a01b036000541633036119fd57565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b6001600160a01b03809116918215611c435716918215611bd9578015158080611bcf575b611b33575b5060008281526001602052604081205491808310611ac957604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef95876020965260018652038282205586815220818154019055604051908152a3565b608460405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152fd5b611b3b611779565b90611b4a602083015192611411565b9080611bc5575b611b5c575b50611a6a565b611b6860039184611848565b91016000908482528060205260408220611b8384825461185b565b905585825260205260408120908154818482019485129112908015821691151617611bb15750553880611b56565b80634e487b7160e01b602492526011600452fd5b5084841415611b51565b5083831415611a65565b608460405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152fd5b608460405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152fd5b6001600160a01b03809116918215611d785716918215611d0e5760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925918360005260028252604060002085600052825280604060002055604051908152a3565b608460405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152fd5b608460405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152fdfea26469706673582212204e68fa9ad45b2cc2ff79ead6675b57e3f00659b79f13bf6c62490a8ea896614764736f6c63430008110033000000000000000000000000da00000035fef4082f78def6a8903bee419fbf8e000000000000000000000000ba3335588d9403515223f109edc4eb7269a9ab5d
Deployed Bytecode
0x6080604081815260048036101561001557600080fd5b600092833560e01c90816306fdde031461124f57508063095ea7b31461122557806318160ddd146112065780631bfa4c04146110ef5780631d49d66c1461104b57806323b872dd14610f805780632e1a7d4d14610f63578063313ce56714610e935780633950935114610e445780634216f97214610de95780634e71d92d14610dd05780637026122214610bbf57806370a0823114610b88578063715018a614610b2257806372f702f314610ade57806375619ab5146109fd57806378e3214f146107035780638da5cb5b146106dd57806395d89b41146105db578063a457c2d71461051b578063a9059cbb146104ea578063b6b55f251461031f578063bfe10928146102f7578063d1af0c7d146102b3578063dd62ed3e1461026a578063e9fad8ee146102355763f2fde38b1461014c57600080fd5b346102315760203660031901126102315761016561138c565b9061016e6119e9565b6001600160a01b038092169283156101c857505082548273ffffffffffffffffffffffffffffffffffffffff198216178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b906020608492519162461bcd60e51b8352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b8280fd5b50503461026657816003193601126102665761025b9033835260016020528220546114b7565b6102636116af565b80f35b5080fd5b5050346102665780600319360112610266578060209261028861138c565b6102906113a7565b6001600160a01b0391821683526002865283832091168252845220549051908152f35b505034610266578160031936011261026657602090516001600160a01b037f000000000000000000000000ba3335588d9403515223f109edc4eb7269a9ab5d168152f35b5050346102665781600319360112610266576020906001600160a01b03600654169051908152f35b503461023157602091826003193601126104e65781359233156104a557831515808061049d575b610407575b5060019061035b85600354611756565b6003553386528181528286208581540190558251858152867fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef833393a3338652526d04ee2d6d415b85acef810000000081852054116103e157836102638430337f000000000000000000000000da00000035fef4082f78def6a8903bee419fbf8e6118ae565b517f24691f6b000000000000000000000000000000000000000000000000000000008152fd5b61040f611779565b9061041d8383015192611411565b9080610495575b61042f575b5061034b565b4264ffffffffff16602882901b64ffffffffff19161760028301556003906104579087611848565b9133885201825282862080548783820193841291129080158216911516176104825755600138610429565b602487601187634e487b7160e01b835252fd5b506001610424565b506001610346565b60649291519162461bcd60e51b8352820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152fd5b8380fd5b50503461026657806003193601126102665760209061051461050a61138c565b6024359033611a41565b5160018152f35b5082346105d857826003193601126105d85761053561138c565b91836024359233815260026020528181206001600160a01b038616825260205220549082821061056f576020856105148585038733611cad565b608490602086519162461bcd60e51b8352820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152fd5b80fd5b509034610231578260031936011261023157805191836005549060019082821c9282811680156106d3575b60209586861082146106c0575084885290811561069e5750600114610645575b6106418686610637828b03836113ef565b5191829182611343565b0390f35b929550600583527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db05b82841061068b575050508261064194610637928201019438610626565b805486850188015292860192810161066e565b60ff191687860152505050151560051b83010192506106378261064138610626565b836022602492634e487b7160e01b835252fd5b93607f1693610606565b5050346102665781600319360112610266576001600160a01b0360209254169051908152f35b5090346102315780600319360112610231576001600160a01b038235818116929183820361092c576024938435928260065416918233036109ee578061085c575050506006541681471061081a578580809381935af13d15610815573d67ffffffffffffffff811161080357825190610786601f8201601f1916602001836113ef565b81528560203d92013e5b1561079b5750505080f35b608492916020603a92519362461bcd60e51b85528401528201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152fd5b8386604187634e487b7160e01b835252fd5b610790565b606485601d86602087519362461bcd60e51b85528401528201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152fd5b909395919492809897987f000000000000000000000000da00000035fef4082f78def6a8903bee419fbf8e16908183146000146109425750602091508351928380926370a0823160e01b8252308c8301525afa908115610938578691610903575b506108ca85600354611756565b116108db575061026393945061194f565b8590517f356680b7000000000000000000000000000000000000000000000000000000008152fd5b90506020813d8211610930575b8161091d602093836113ef565b8101031261092c5751386108bd565b8580fd5b3d9150610910565b82513d88823e3d90fd5b90507f000000000000000000000000ba3335588d9403515223f109edc4eb7269a9ab5d1680911461097c575b50505061026393945061194f565b6020908351928380926370a0823160e01b8252308c8301525afa9081156109385786916109bd575b506109b185600854611756565b116108db57808061096e565b90506020813d82116109e6575b816109d7602093836113ef565b8101031261092c5751386109a4565b3d91506109ca565b878651634ca8886760e01b8152fd5b50903461023157602036600319011261023157610a1861138c565b90610a216119e9565b6001600160a01b03809216928315610ab75760065492831690818514610a905750817fa9f739537fc57540bed0a44e33e27baa63290d865cc15f0f16cf17d38c998a4d9173ffffffffffffffffffffffffffffffffffffffff19949351908152856020820152a1161760065580f35b82517f8750ee90000000000000000000000000000000000000000000000000000000008152fd5b90517f71702079000000000000000000000000000000000000000000000000000000008152fd5b505034610266578160031936011261026657602090516001600160a01b037f000000000000000000000000da00000035fef4082f78def6a8903bee419fbf8e168152f35b83346105d857806003193601126105d857610b3b6119e9565b806001600160a01b03815473ffffffffffffffffffffffffffffffffffffffff1981168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50503461026657602036600319011261026657806020926001600160a01b03610baf61138c565b1681526001845220549051908152f35b5090346102315780600319360112610231578135916024356001600160a01b03600654163303610dc157610bf1611779565b610c20610c02602083015192611411565b4264ffffffffff1660289190911b64ffffffffff1916176002830155565b84928215610d9a5763ffffffff90818411610d735782549064ffffffffff90818316926001860193845495814210610d2c575b5050506d04ee2d6d415b85acef81000000008711610d05575091859391610cad7f3efe2b1ade87153c913a322f09a35c930d7fd699770b8d7cdd294e1debf6e9e4978795610ca66102639c9b9942611756565b1693611756565b905568ffffffffffffffffff198460481b1668ffffffff00000000008460281b161717905582519182526020820152a130337f000000000000000000000000ba3335588d9403515223f109edc4eb7269a9ab5d6118ae565b87517f06250401000000000000000000000000000000000000000000000000000000008152fd5b610d6a939950610d5a85610d538594670de0b6b3a764000094610d649760281c1690611824565b16896117b8565b049060481c61183b565b89611756565b95388080610c53565b85517f426a1073000000000000000000000000000000000000000000000000000000008152fd5b84517f68d5686e000000000000000000000000000000000000000000000000000000008152fd5b509051634ca8886760e01b8152fd5b83346105d857806003193601126105d8576102636116af565b50503461026657602036600319011261026657610e3d602092610e0a61138c565b83610e13611779565b926001600160a01b038316815260018752205490610e376002878501510193611411565b92611874565b9051908152f35b505034610266578060031936011261026657610514602092610e8c610e6761138c565b91338152600286528481206001600160a01b0384168252865284602435912054611756565b9033611cad565b5091346105d857806003193601126105d8576020825180947f313ce567000000000000000000000000000000000000000000000000000000008252816001600160a01b037f000000000000000000000000da00000035fef4082f78def6a8903bee419fbf8e165afa928315610f57578193610f16575b60208460ff855191168152f35b9092506020813d8211610f4f575b81610f31602093836113ef565b8101031261023157519160ff831683036105d8575060ff6020610f09565b3d9150610f24565b509051903d90823e3d90fd5b8382346102665760203660031901126102665761026390356114b7565b5082903461026657606036600319011261026657610f9c61138c565b610fa46113a7565b9184604435946001600160a01b038416815260026020528181203382526020522054906000198203610fdf575b602086610514878787611a41565b8482106110085750918391610ffd6020969561051495033383611cad565b919394819350610fd1565b606490602087519162461bcd60e51b8352820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152fd5b5050346102665781600319360112610266576080916060825161106d816113bd565b828152826020820152828482015201528051611088816113bd565b6007549176ffffffffffffffffffffffffffffffffffffffffffffff64ffffffffff8416938484526020840163ffffffff90818360281c1681528486019260481c835260606008549601958652845196875251166020860152511690830152516060820152f35b50346102315782600319360112610231576001600160a01b036006541633036111f857507f3efe2b1ade87153c913a322f09a35c930d7fd699770b8d7cdd294e1debf6e9e461113c611779565b9161116c61114e602085015194611411565b4264ffffffffff1660289190911b64ffffffffff1916176002850155565b8254926111a264ffffffffff94670de0b6b3a7640000610d5a8761119b63ffffffff8560281c16828616611824565b16856117b8565b93600182016111b286825461183b565b9055421690558051848152846020820152a1806111cd575080f35b61026390337f000000000000000000000000ba3335588d9403515223f109edc4eb7269a9ab5d61194f565b9051634ca8886760e01b8152fd5b5050346102665781600319360112610266576020906003549051908152f35b50503461026657806003193601126102665760209061051461124561138c565b6024359033611cad565b90508284346105d857806003193601126105d857809380549160019083821c92828516948515611339575b60209586861081146113265785895290811561130257506001146112aa575b6106418787610637828c03836113ef565b81529295507f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b8284106112ef57505050826106419461063792820101948680611299565b80548685018801529286019281016112d1565b60ff19168887015250505050151560051b8301019250610637826106418680611299565b602484602285634e487b7160e01b835252fd5b93607f169361127a565b6020808252825181830181905290939260005b82811061137857505060409293506000838284010152601f8019910116010190565b818101860151848201604001528501611356565b600435906001600160a01b03821682036113a257565b600080fd5b602435906001600160a01b03821682036113a257565b6080810190811067ffffffffffffffff8211176113d957604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176113d957604052565b602081016002815101549064ffffffffff82169160281c92824203611437575b50505090565b61143f61148d565b505160031461145e57634e487b7160e01b600052605160045260246000fd5b600354908115611431576114849261147f9161147861148d565b50516117b8565b611798565b01388080611431565b604051906040820182811067ffffffffffffffff8211176113d95760405260006020838281520152565b331561164557801515808061163d575b6115c2575b503360005260016020526040600020549080821061155857806115569233600052600160205203604060002055806003540360035560006040518281527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60203392a3337f000000000000000000000000da00000035fef4082f78def6a8903bee419fbf8e61194f565b565b608460405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152fd5b6115ca611779565b906115d9602083015192611411565b9080611635575b6115eb575b506114cc565b4264ffffffffff16602882901b64ffffffffff19161760028301556003906116139084611848565b91336000520160205261162c604060002091825461185b565b905538806115e5565b5060016115e0565b5060016114c7565b608460405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152fd5b6116b7611779565b3360005260016020526040600020546116d4602083015192611411565b6116e381833360028701611874565b928315159283611723575b5050506116f85750565b61155690337f000000000000000000000000ba3335588d9403515223f109edc4eb7269a9ab5d61194f565b60019261172f91611848565b33600052600382016020526040600020550161174c83825461183b565b90553880806116ee565b9190820180921161176357565b634e487b7160e01b600052601160045260246000fd5b61178161148d565b5061178a61148d565b600381526007602082015290565b81156117a2570490565b634e487b7160e01b600052601260045260246000fd5b91906000925464ffffffffff81169063ffffffff8160281c1692836117dd5750505050565b61181394955090670de0b6b3a7640000929182421060001461181e5742925b808210156118165750905b60481c91030202611798565b90565b905090611807565b826117fc565b64ffffffffff918216908216039190821161176357565b9190820391821161176357565b8181029291811591840414171561176357565b8181039291600013801582851316918412161761176357565b6001906001600160a01b03611895670de0b6b3a7640000966118aa96611848565b9316600052016020526040600020549061185b565b0490565b9260209291606491600093604051927f23b872dd00000000000000000000000000000000000000000000000000000000845260048401526024830152604482015282855af1908161192c575b501561190257565b60046040517ff4059071000000000000000000000000000000000000000000000000000000008152fd5b90503d156119475750600160005114601f3d11165b386118fa565b3b1515611941565b916044602092600092604051917fa9059cbb0000000000000000000000000000000000000000000000000000000083526004830152602482015282855af190816119c6575b501561199c57565b60046040517ffb7f5079000000000000000000000000000000000000000000000000000000008152fd5b90503d156119e15750600160005114601f3d11165b38611994565b3b15156119db565b6001600160a01b036000541633036119fd57565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b6001600160a01b03809116918215611c435716918215611bd9578015158080611bcf575b611b33575b5060008281526001602052604081205491808310611ac957604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef95876020965260018652038282205586815220818154019055604051908152a3565b608460405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152fd5b611b3b611779565b90611b4a602083015192611411565b9080611bc5575b611b5c575b50611a6a565b611b6860039184611848565b91016000908482528060205260408220611b8384825461185b565b905585825260205260408120908154818482019485129112908015821691151617611bb15750553880611b56565b80634e487b7160e01b602492526011600452fd5b5084841415611b51565b5083831415611a65565b608460405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152fd5b608460405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152fd5b6001600160a01b03809116918215611d785716918215611d0e5760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925918360005260028252604060002085600052825280604060002055604051908152a3565b608460405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152fd5b608460405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152fdfea26469706673582212204e68fa9ad45b2cc2ff79ead6675b57e3f00659b79f13bf6c62490a8ea896614764736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000da00000035fef4082f78def6a8903bee419fbf8e000000000000000000000000ba3335588d9403515223f109edc4eb7269a9ab5d
-----Decoded View---------------
Arg [0] : stakingToken_ (address): 0xda00000035fef4082F78dEF6A8903bee419FbF8E
Arg [1] : rewardsToken_ (address): 0xBa3335588D9403515223F109EdC4eB7269a9Ab5D
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000da00000035fef4082f78def6a8903bee419fbf8e
Arg [1] : 000000000000000000000000ba3335588d9403515223f109edc4eb7269a9ab5d
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.011866 | 11,688,483.3223 | $138,696.91 |
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.