Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
StakingFactory
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import { Clones } from "@openzeppelin/contracts/proxy/Clones.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import { IStakingBase } from "./interfaces/templates/base/IStakingBase.sol"; import { IStakingFactory } from "./interfaces/IStakingFactory.sol"; /// @title Factory to deploy staking protocol templates /// @author 0xdEaF <[email protected]> /// @notice each staking template has its own factory. It's using cloning to make a contract creation as cheap as possible contract StakingFactory is IStakingFactory, ReentrancyGuard { using EnumerableSet for EnumerableSet.AddressSet; /// @notice address of the staking template address public immutable implementation; /// @dev keeps track of the protocol that is deployed by a certain service provider mapping(address deployer => EnumerableSet.AddressSet protocol) private _protocols; /// @dev stores all protocols address[] private allProtocols; /// Construct /// @param _implementation address of the staking template constructor(address _implementation) { if (_implementation == address(0)) revert StakingFactory__AddressZero(); implementation = _implementation; } /// @inheritdoc IStakingFactory function createStaking(StakingCreateParams calldata _params) external payable nonReentrant returns (address _stakingProtocol) { if (_params.deployer == address(0)) revert StakingFactory__AddressZero(); _stakingProtocol = Clones.clone(implementation); IStakingBase(_stakingProtocol).initialize(_params.stakingToken, _params.owner, _params.args); allProtocols.push(_stakingProtocol); _protocols[_params.deployer].add(_stakingProtocol); if (msg.value > 0) Address.sendValue(payable(_params.deployer), msg.value); emit Created(_params.deployer, _params.owner, _stakingProtocol, msg.value); } /// @inheritdoc IStakingFactory function getProtocols(uint256 _limit, uint256 _offset) external view returns (address[] memory _response, uint256 _count) { _count = getProtocolsCount(); _limit = _maxLimit(_limit, _offset, _count); _response = new address[](_limit); for (uint256 _start = 0; _start + _offset < _limit + _offset; _start++) _response[_start] = allProtocols[_start + _offset]; } /// @inheritdoc IStakingFactory function getProtocolsCount() public view returns (uint256 _count) { _count = allProtocols.length; } /// @inheritdoc IStakingFactory function getProtocolsForDeployer( address _deployer, uint256 _limit, uint256 _offset ) external view returns (address[] memory _response, uint256 _count) { _count = getProtocolsForDeployerCount(_deployer); _limit = _maxLimit(_limit, _offset, _count); _response = new address[](_limit); for (uint256 _start = 0; _start + _offset < _limit + _offset; _start++) _response[_start] = _protocols[_deployer].at(_start + _offset); } /// @inheritdoc IStakingFactory function getProtocolsForDeployerCount(address _deployer) public view returns (uint256 _count) { _count = _protocols[_deployer].length(); } /// Helper function to figure out the max limit of a list /// @param limit limit that has been targeted /// @param offset offset that has been targeted /// @param count the amount of entries the calculation should be based on /// @dev is used to not overflow the possible available limits of a list function _maxLimit(uint256 limit, uint256 offset, uint256 count) internal pure returns (uint256) { if (limit + offset > count && offset < count) return count - offset; else if (limit + offset <= count) return limit; else return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (proxy/Clones.sol) pragma solidity ^0.8.20; import {Errors} from "../utils/Errors.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-1167[ERC-1167] is a standard for * deploying minimal proxy contracts, also known as "clones". * * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies * > a minimal bytecode implementation that delegates all calls to a known, fixed address. * * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2` * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the * deterministic method. */ library Clones { /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. * * This function uses the create opcode, which should never revert. */ function clone(address implementation) internal returns (address instance) { return clone(implementation, 0); } /** * @dev Same as {xref-Clones-clone-address-}[clone], but with a `value` parameter to send native currency * to the new contract. * * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory) * to always have enough balance for new deployments. Consider exposing this function under a payable method. */ function clone(address implementation, uint256 value) internal returns (address instance) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } assembly ("memory-safe") { // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes // of the `implementation` address with the bytecode before the address. mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) instance := create(value, 0x09, 0x37) } if (instance == address(0)) { revert Errors.FailedDeployment(); } } /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. * * This function uses the create2 opcode and a `salt` to deterministically deploy * the clone. Using the same `implementation` and `salt` multiple time will revert, since * the clones cannot be deployed twice at the same address. */ function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) { return cloneDeterministic(implementation, salt, 0); } /** * @dev Same as {xref-Clones-cloneDeterministic-address-bytes32-}[cloneDeterministic], but with * a `value` parameter to send native currency to the new contract. * * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory) * to always have enough balance for new deployments. Consider exposing this function under a payable method. */ function cloneDeterministic( address implementation, bytes32 salt, uint256 value ) internal returns (address instance) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } assembly ("memory-safe") { // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes // of the `implementation` address with the bytecode before the address. mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) instance := create2(value, 0x09, 0x37, salt) } if (instance == address(0)) { revert Errors.FailedDeployment(); } } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress( address implementation, bytes32 salt, address deployer ) internal pure returns (address predicted) { assembly ("memory-safe") { let ptr := mload(0x40) mstore(add(ptr, 0x38), deployer) mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff) mstore(add(ptr, 0x14), implementation) mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73) mstore(add(ptr, 0x58), salt) mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37)) predicted := and(keccak256(add(ptr, 0x43), 0x55), 0xffffffffffffffffffffffffffffffffffffffff) } } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress( address implementation, bytes32 salt ) internal view returns (address predicted) { return predictDeterministicAddress(implementation, salt, address(this)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert Errors.FailedCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly ("memory-safe") { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at, * consider using {ReentrancyGuardTransient} instead. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; assembly ("memory-safe") { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly ("memory-safe") { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly ("memory-safe") { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; /// @title Interface of the factory that is creating the staking protocols /// @author 0xdEaF <[email protected]> /// @notice each protocol will have its own factory interface IStakingFactory { error StakingFactory__AddressZero(); /// Create protocol event /// @param deployer the address that should identify the service provider /// @param owner address of the desired owner /// @param protocol address of the created protocol /// @param paid msg.value that has been sent to the create method in order to pay for creation /// @dev msg.value will be send to address of deployer event Created(address indexed deployer, address indexed owner, address indexed protocol, uint256 paid); struct StakingCreateParams { /// @dev address of the staking token address stakingToken; /// @dev address of the service provider that handles the deployment address deployer; /// @dev address of the desired owner address owner; /// @dev encoded string that can be handled by any future staking template being created bytes args; } /// Creates a new staking protocol based on a given template /// @param params parameters for the creation of the new protocol function createStaking(StakingCreateParams calldata params) external payable returns (address stakingProtocol); /// Returns a list of protocols addresses and the number of available protocols /// @param limit amount of addresses /// @param offset index to start from until limit /// @return response list of addresses /// @return count total amount of protocols function getProtocols(uint256 limit, uint256 offset) external view returns (address[] memory response, uint256 count); /// Total amount of protocols /// @return count total amount of protocols function getProtocolsCount() external view returns (uint256 count); /// Returns a list of protocols based on the service provider address /// @param deployer address of the service provider /// @param limit amount of addresses /// @param offset index to start from until limit /// @return response list of addresses /// @return count total amount of protocols function getProtocolsForDeployer( address deployer, uint256 limit, uint256 offset ) external view returns (address[] memory response, uint256 count); /// Total amount of protocols for a certain service provider /// @param deployer address of the service provider /// @return count total amount of protocols function getProtocolsForDeployerCount(address deployer) external view returns (uint256 count); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.28; /// @title Interface for the base function of each staking template /// @author 0xdEaF <[email protected]> interface IStakingBase { error Staking__NoStakes(); error Staking__AmountZero(); error Staking__AmountOverflow(); error Staking__AmountReceivedInsufficient(uint256 actualAmount, uint256 minAmount); error Staking__ValueNotAllowed(); error Staking__AddressZero(); error Staking__InvalidAmount(); error Staking__InsufficientStake(); /// Deposit stake event /// @param staker address of staker /// @param amount deposited amount event Deposit(address indexed staker, int256 amount); /// Withdraw stake event /// @param staker address of staker /// @param amount withdrawn amount event Withdraw(address indexed staker, int256 amount); /// Update stake event /// @param staker address of staker /// @param amount updated amount event Update(address indexed staker, int256 amount); /// Claim rewards event /// @param staker address of staker /// @param amount rewarded amount event Claim(address indexed staker, uint256 amount); /// Restake rewards event /// @param staker address of staker /// @param amount restake amount event Restaked(address indexed staker, uint256 amount); /// Rewards injected event /// @param actor address of reward injector /// @param amountInjected amount of rewards injected /// @param amountGiven amount that actually has been given (can differ from amountInjected) /// @param amountStaked staked amount (interesting value for for apr calculation) event InjectRewards(address indexed actor, uint256 amountInjected, uint256 amountGiven, uint256 amountStaked); /// Service fee event /// @param provider address of the service provide /// @param paymentAmount fee amount of the service provider (always native currency of desired chain) event ServiceFee(address indexed provider, uint256 paymentAmount); /// Service fee transfer failed event /// @param provider address of the receiver /// @param paymentAmount fee amount of the service provider (always native currency of desired chain) event ServiceFeeFailed(address indexed provider, uint256 paymentAmount); /// @dev struct for storing the stake struct Stake { /// @dev amount of stake uint128 amount; /// @dev amount of the pending stake will be stored in case of restaking uint256 pending; /// @dev scaled dividend uint256 dividend; } /// @dev struct for list response of stake struct StakersStake { /// @dev address of the staker address staker; /// @dev amount of stake uint128 amount; /// @dev amount of the pending stake will be stored in case of restaking uint256 pending; /// @dev scaled dividend uint256 dividend; } /// Initialize function for the protocol /// @param stakingToken token address that will be used for the staking token /// @param owner address of the owner of the protocol /// @param args encoded parameters that will be used for the specific template function initialize(address stakingToken, address owner, bytes calldata args) external; /// Enabled or disables a protocol /// @param enable enable/disable flag /// @param referrals address referrals that receive an evenly spread share of sent value function enable(bool enable, address[] calldata referrals) external payable; /// Deposits a stake for a given staker with a given amount /// @param staker address of the staker /// @param amount amount of staking token that should be staked /// @param minAmount min amount of expected staking tokens that will be staked /// @param referrals address referrals that receive an evenly spread share of sent value function deposit( address staker, uint256 amount, uint256 minAmount, address[] calldata referrals ) external payable returns (uint256 depositAmount); /// Withdraws to a specified receiver /// @param receiver address of the receiver of the withdrawing stake /// @param amount amount of stake that should be withdrawn /// @param referrals address referrals that receive an evenly spread share of sent value function withdraw(address receiver, uint256 amount, address[] calldata referrals) external payable returns (uint256 withdrawAmount); /// Restakes the rewards of the sender /// @param referrals address referrals that receive an evenly spread share of sent value function restake(address[] calldata referrals) external payable returns (uint256 restakeAmount); /// Claims rewards of the sender and sends it to a specified receiver /// @param receiver address of the reward receiver /// @param referrals address referrals that receive an evenly spread share of sent value function claimRewards(address receiver, address[] calldata referrals) external payable returns (uint256 claimAmount); /// Deposit and distribute rewards to stakers /// @param amount amount of reward token that should be distributed /// @param minAmount min amount of expected rewards tokens that will be distributed /// @param referrals address referrals that receive an evenly spread share of sent value function injectRewards( uint256 amount, uint256 minAmount, address[] calldata referrals ) external payable returns (uint256 injectedAmount); /// @dev total amount of staked tokens function staked() external view returns (uint128); /// Total amount of a given reward token /// @param rewardToken address of the reward token function rewarded(address rewardToken) external view returns (uint256 amount); /// @dev address of the staking token function stakingToken() external view returns (address); /// @dev address of the reward token function rewardToken() external view returns (address); /// Pending rewards of a given staker /// @param staker address of staker function getPendingRewards(address staker) external view returns (uint256 pendingRewards); /// Stake information of a given staker /// @param staker address of staker function getStakeOf(address staker) external view returns (Stake memory stake); /// Total given rewards of a given staker /// @param staker address of staker function getRewardsOf(address staker) external view returns (uint256 rewards); /// Paginated list of stakers with the total amount /// @param _limit amount of stakers /// @param _offset index to start from until limit /// @return _stakers staker information /// @return _count total amount of stakers available function getStakers(uint256 _limit, uint256 _offset) external view returns (StakersStake[] memory _stakers, uint256 _count); /// Total amount of stakers function getStakersCount() external view returns (uint256 _count); }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_implementation","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"FailedDeployment","type":"error"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"StakingFactory__AddressZero","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"deployer","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"protocol","type":"address"},{"indexed":false,"internalType":"uint256","name":"paid","type":"uint256"}],"name":"Created","type":"event"},{"inputs":[{"components":[{"internalType":"address","name":"stakingToken","type":"address"},{"internalType":"address","name":"deployer","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes","name":"args","type":"bytes"}],"internalType":"struct IStakingFactory.StakingCreateParams","name":"_params","type":"tuple"}],"name":"createStaking","outputs":[{"internalType":"address","name":"_stakingProtocol","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"},{"internalType":"uint256","name":"_offset","type":"uint256"}],"name":"getProtocols","outputs":[{"internalType":"address[]","name":"_response","type":"address[]"},{"internalType":"uint256","name":"_count","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProtocolsCount","outputs":[{"internalType":"uint256","name":"_count","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_deployer","type":"address"},{"internalType":"uint256","name":"_limit","type":"uint256"},{"internalType":"uint256","name":"_offset","type":"uint256"}],"name":"getProtocolsForDeployer","outputs":[{"internalType":"address[]","name":"_response","type":"address[]"},{"internalType":"uint256","name":"_count","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_deployer","type":"address"}],"name":"getProtocolsForDeployerCount","outputs":[{"internalType":"uint256","name":"_count","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a060405234801561001057600080fd5b50604051610b0c380380610b0c83398101604081905261002f9161006c565b60016000556001600160a01b03811661005b57604051632c5a01fd60e11b815260040160405180910390fd5b6001600160a01b031660805261009c565b60006020828403121561007e57600080fd5b81516001600160a01b038116811461009557600080fd5b9392505050565b608051610a4f6100bd6000396000818160a301526102930152610a4f6000f3fe6080604052600436106100555760003560e01c80634f8447d61461005a5780635c60da1b1461009157806374cb1936146100dd5780637651a6b9146100f05780637a89680f1461010f578063ef3414851461012f575b600080fd5b34801561006657600080fd5b5061007a6100753660046107e9565b61014f565b60405161008892919061080b565b60405180910390f35b34801561009d57600080fd5b506100c57f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610088565b6100c56100eb366004610861565b61024b565b3480156100fc57600080fd5b506002545b604051908152602001610088565b34801561011b57600080fd5b5061010161012a3660046108b3565b61046a565b34801561013b57600080fd5b5061007a61014a3660046108ce565b610491565b6060600061015c60025490565b905061016984848361057f565b93508367ffffffffffffffff81111561018457610184610901565b6040519080825280602002602001820160405280156101ad578160200160208202803683370190505b50915060005b6101bd848661092d565b6101c7858361092d565b10156102435760026101d9858361092d565b815481106101e9576101e9610940565b9060005260206000200160009054906101000a90046001600160a01b031683828151811061021957610219610940565b6001600160a01b03909216602092830291909101909101528061023b81610956565b9150506101b3565b509250929050565b60006102556105d0565b600061026760408401602085016108b3565b6001600160a01b03160361028e57604051632c5a01fd60e11b815260040160405180910390fd5b6102b77f00000000000000000000000000000000000000000000000000000000000000006105fa565b90506001600160a01b03811663cf7a1d776102d560208501856108b3565b6102e560608601604087016108b3565b6102f2606087018761096f565b6040518563ffffffff1660e01b815260040161031194939291906109bd565b600060405180830381600087803b15801561032b57600080fd5b505af115801561033f573d6000803e3d6000fd5b5050600280546001808201835560009283527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90910180546001600160a01b0319166001600160a01b0387161790556103c69350849250906103a760408701602088016108b3565b6001600160a01b03168152602081019190915260400160002090610607565b5034156103e6576103e66103e060408401602085016108b3565b3461061c565b6001600160a01b03811661040060608401604085016108b3565b6001600160a01b031661041960408501602086016108b3565b6001600160a01b03167f9f94c44dd7c05df7528cfb5aedb137fa0cee080fb3fb54cec59f157b4424b18a3460405161045391815260200190565b60405180910390a46104656001600055565b919050565b6001600160a01b038116600090815260016020526040812061048b906106c4565b92915050565b6060600061049e8561046a565b90506104ab84848361057f565b93508367ffffffffffffffff8111156104c6576104c6610901565b6040519080825280602002602001820160405280156104ef578160200160208202803683370190505b50915060005b6104ff848661092d565b610509858361092d565b10156105765761053a61051c858361092d565b6001600160a01b0388166000908152600160205260409020906106ce565b83828151811061054c5761054c610940565b6001600160a01b03909216602092830291909101909101528061056e81610956565b9150506104f5565b50935093915050565b60008161058c848661092d565b11801561059857508183105b156105ae576105a78383610a06565b90506105c9565b816105b9848661092d565b116105c55750826105c9565b5060005b9392505050565b6002600054036105f357604051633ee5aeb560e01b815260040160405180910390fd5b6002600055565b600061048b8260006106da565b60006105c9836001600160a01b038416610770565b8047101561064b5760405163cf47918160e01b8152476004820152602481018290526044015b60405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610698576040519150601f19603f3d011682016040523d82523d6000602084013e61069d565b606091505b50509050806106bf5760405163d6bda27560e01b815260040160405180910390fd5b505050565b600061048b825490565b60006105c983836107bf565b6000814710156107065760405163cf47918160e01b815247600482015260248101839052604401610642565b763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b176020526037600983f090506001600160a01b03811661048b5760405163b06ebf3d60e01b815260040160405180910390fd5b60008181526001830160205260408120546107b75750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561048b565b50600061048b565b60008260000182815481106107d6576107d6610940565b9060005260206000200154905092915050565b600080604083850312156107fc57600080fd5b50508035926020909101359150565b6040808252835190820181905260009060208501906060840190835b8181101561084e5783516001600160a01b0316835260209384019390920191600101610827565b5050602093909301939093525092915050565b60006020828403121561087357600080fd5b813567ffffffffffffffff81111561088a57600080fd5b8201608081850312156105c957600080fd5b80356001600160a01b038116811461046557600080fd5b6000602082840312156108c557600080fd5b6105c98261089c565b6000806000606084860312156108e357600080fd5b6108ec8461089c565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561048b5761048b610917565b634e487b7160e01b600052603260045260246000fd5b60006001820161096857610968610917565b5060010190565b6000808335601e1984360301811261098657600080fd5b83018035915067ffffffffffffffff8211156109a157600080fd5b6020019150368190038213156109b657600080fd5b9250929050565b6001600160a01b038581168252841660208201526060604082018190528101829052818360808301376000818301608090810191909152601f909201601f191601019392505050565b8181038181111561048b5761048b61091756fea2646970667358221220983448e41b93b74c71d259c998bd4b9e016f68ab01e849def5cc9f42418a0d0564736f6c634300081c00330000000000000000000000001fdff1297b25b69046a9964a69327544d3dddc82
Deployed Bytecode
0x6080604052600436106100555760003560e01c80634f8447d61461005a5780635c60da1b1461009157806374cb1936146100dd5780637651a6b9146100f05780637a89680f1461010f578063ef3414851461012f575b600080fd5b34801561006657600080fd5b5061007a6100753660046107e9565b61014f565b60405161008892919061080b565b60405180910390f35b34801561009d57600080fd5b506100c57f0000000000000000000000001fdff1297b25b69046a9964a69327544d3dddc8281565b6040516001600160a01b039091168152602001610088565b6100c56100eb366004610861565b61024b565b3480156100fc57600080fd5b506002545b604051908152602001610088565b34801561011b57600080fd5b5061010161012a3660046108b3565b61046a565b34801561013b57600080fd5b5061007a61014a3660046108ce565b610491565b6060600061015c60025490565b905061016984848361057f565b93508367ffffffffffffffff81111561018457610184610901565b6040519080825280602002602001820160405280156101ad578160200160208202803683370190505b50915060005b6101bd848661092d565b6101c7858361092d565b10156102435760026101d9858361092d565b815481106101e9576101e9610940565b9060005260206000200160009054906101000a90046001600160a01b031683828151811061021957610219610940565b6001600160a01b03909216602092830291909101909101528061023b81610956565b9150506101b3565b509250929050565b60006102556105d0565b600061026760408401602085016108b3565b6001600160a01b03160361028e57604051632c5a01fd60e11b815260040160405180910390fd5b6102b77f0000000000000000000000001fdff1297b25b69046a9964a69327544d3dddc826105fa565b90506001600160a01b03811663cf7a1d776102d560208501856108b3565b6102e560608601604087016108b3565b6102f2606087018761096f565b6040518563ffffffff1660e01b815260040161031194939291906109bd565b600060405180830381600087803b15801561032b57600080fd5b505af115801561033f573d6000803e3d6000fd5b5050600280546001808201835560009283527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace90910180546001600160a01b0319166001600160a01b0387161790556103c69350849250906103a760408701602088016108b3565b6001600160a01b03168152602081019190915260400160002090610607565b5034156103e6576103e66103e060408401602085016108b3565b3461061c565b6001600160a01b03811661040060608401604085016108b3565b6001600160a01b031661041960408501602086016108b3565b6001600160a01b03167f9f94c44dd7c05df7528cfb5aedb137fa0cee080fb3fb54cec59f157b4424b18a3460405161045391815260200190565b60405180910390a46104656001600055565b919050565b6001600160a01b038116600090815260016020526040812061048b906106c4565b92915050565b6060600061049e8561046a565b90506104ab84848361057f565b93508367ffffffffffffffff8111156104c6576104c6610901565b6040519080825280602002602001820160405280156104ef578160200160208202803683370190505b50915060005b6104ff848661092d565b610509858361092d565b10156105765761053a61051c858361092d565b6001600160a01b0388166000908152600160205260409020906106ce565b83828151811061054c5761054c610940565b6001600160a01b03909216602092830291909101909101528061056e81610956565b9150506104f5565b50935093915050565b60008161058c848661092d565b11801561059857508183105b156105ae576105a78383610a06565b90506105c9565b816105b9848661092d565b116105c55750826105c9565b5060005b9392505050565b6002600054036105f357604051633ee5aeb560e01b815260040160405180910390fd5b6002600055565b600061048b8260006106da565b60006105c9836001600160a01b038416610770565b8047101561064b5760405163cf47918160e01b8152476004820152602481018290526044015b60405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610698576040519150601f19603f3d011682016040523d82523d6000602084013e61069d565b606091505b50509050806106bf5760405163d6bda27560e01b815260040160405180910390fd5b505050565b600061048b825490565b60006105c983836107bf565b6000814710156107065760405163cf47918160e01b815247600482015260248101839052604401610642565b763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b176020526037600983f090506001600160a01b03811661048b5760405163b06ebf3d60e01b815260040160405180910390fd5b60008181526001830160205260408120546107b75750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561048b565b50600061048b565b60008260000182815481106107d6576107d6610940565b9060005260206000200154905092915050565b600080604083850312156107fc57600080fd5b50508035926020909101359150565b6040808252835190820181905260009060208501906060840190835b8181101561084e5783516001600160a01b0316835260209384019390920191600101610827565b5050602093909301939093525092915050565b60006020828403121561087357600080fd5b813567ffffffffffffffff81111561088a57600080fd5b8201608081850312156105c957600080fd5b80356001600160a01b038116811461046557600080fd5b6000602082840312156108c557600080fd5b6105c98261089c565b6000806000606084860312156108e357600080fd5b6108ec8461089c565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561048b5761048b610917565b634e487b7160e01b600052603260045260246000fd5b60006001820161096857610968610917565b5060010190565b6000808335601e1984360301811261098657600080fd5b83018035915067ffffffffffffffff8211156109a157600080fd5b6020019150368190038213156109b657600080fd5b9250929050565b6001600160a01b038581168252841660208201526060604082018190528101829052818360808301376000818301608090810191909152601f909201601f191601019392505050565b8181038181111561048b5761048b61091756fea2646970667358221220983448e41b93b74c71d259c998bd4b9e016f68ab01e849def5cc9f42418a0d0564736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001fdff1297b25b69046a9964a69327544d3dddc82
-----Decoded View---------------
Arg [0] : _implementation (address): 0x1FDFf1297B25B69046a9964A69327544D3DDdC82
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000001fdff1297b25b69046a9964a69327544d3dddc82
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.