Source Code
Overview
S Balance
0 S
More Info
ContractCreator
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
5086519 | 12 hrs ago | 0 S |
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 Name:
RewarderFactory
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 800 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {Ownable2StepUpgradeable} from "openzeppelin-contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import {ImmutableClone} from "../libraries/ImmutableClone.sol"; import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; import {IRewarder} from "../interfaces/IRewarder.sol"; import {IBribeRewarder} from "../interfaces/IBribeRewarder.sol"; import {IBaseRewarder} from "../interfaces/IBaseRewarder.sol"; import {IRewarderFactory} from "../interfaces/IRewarderFactory.sol"; /** * @title Rewarder Factory Contract * @dev The Rewarder Factory Contract allows users to create bribe rewarders and admin to create masterchef. */ contract RewarderFactory is Ownable2StepUpgradeable, IRewarderFactory { mapping(RewarderType => IRewarder) private _implementations; mapping(RewarderType => IRewarder[]) private _rewarders; mapping(IRewarder => RewarderType) private _rewarderTypes; mapping(address => uint256) private _nonces; /// @dev holds whitelisted tokens with their minBribeAmount (> 0) as bribe amount per period // minAmount == 0 means token is not whitelisted mapping(address => uint256) private _whitelistedTokens; /// @dev fee for creating bribes in native token uint256 private _bribeCreatorFee; uint256[10] __gap; /** * @dev Disables the initialize function. */ constructor() { _disableInitializers(); } /** * @dev Initializes the RewarderFactory contract. * @param initialOwner The initial owner of the contract. */ function initialize( address initialOwner, RewarderType[] calldata initialRewarderTypes, IRewarder[] calldata initialRewarders ) external reinitializer(1) { __Ownable_init(initialOwner); uint256 length = initialRewarderTypes.length; for (uint256 i; i < length; ++i) { _setRewarderImplementation(initialRewarderTypes[i], initialRewarders[i]); } _bribeCreatorFee = 0; // maybe in the future for non-whitelisted tokens } /** * @dev get the fee for creating bribes in native token decimals */ function getBribeCreatorFee() external view returns (uint256) { return _bribeCreatorFee; } /** * @dev Returns if token is whitelisted and the minBribeAmount * * @param token token address * @return isWhitelisted true if whitelisted * @return minBribeAmount min bribe amount per period */ function getWhitelistedTokenInfo (address token) external view returns (bool isWhitelisted, uint256 minBribeAmount) { minBribeAmount = _whitelistedTokens[token]; isWhitelisted = minBribeAmount > 0; } /** * @dev Returns the rewarder implementation for the given rewarder type. * @param rewarderType The rewarder type. * @return The rewarder implementation for the given rewarder type. */ function getRewarderImplementation(RewarderType rewarderType) external view returns (IRewarder) { return _implementations[rewarderType]; } /** * @dev Returns the number of rewarders for the given rewarder type. * @param rewarderType The rewarder type. * @return The number of rewarders for the given rewarder type. */ function getRewarderCount(RewarderType rewarderType) external view returns (uint256) { return _rewarders[rewarderType].length; } /** * @dev Returns the rewarder at the given index for the given rewarder type. * @param rewarderType The rewarder type. * @param index The index of the rewarder. * @return The rewarder at the given index for the given rewarder type. */ function getRewarderAt(RewarderType rewarderType, uint256 index) external view returns (IRewarder) { return _rewarders[rewarderType][index]; } /** * @dev Returns the rewarder type for the given rewarder. * @param rewarder The rewarder. * @return The rewarder type for the given rewarder. */ function getRewarderType(IRewarder rewarder) external view returns (RewarderType) { return _rewarderTypes[rewarder]; } /** * @dev Creates a rewarder. * Only the owner can call this function, except for veMoe rewarders. * @param rewarderType The rewarder type. * @param token The token to reward. * @param pid The pool ID. * @return rewarder The rewarder. */ function createRewarder(RewarderType rewarderType, IERC20 token, uint256 pid) external returns (IBaseRewarder rewarder) { _checkOwner(); if (rewarderType == RewarderType.BribeRewarder) revert RewarderFactory__InvalidRewarderType(); rewarder = _clone(rewarderType, token, pid); emit RewarderCreated(rewarderType, token, pid, rewarder); } /** * @dev Create a bribe rewarder * Everyone can call this function. The bribe token needs to be whitelisted * @param token The token to reward. * @param pool The pool address * @return rewarder The rewarder. */ function createBribeRewarder(IERC20 token, address pool) external returns (IBribeRewarder rewarder) { _checkWhitelist(address(token)); rewarder = IBribeRewarder(_cloneBribe(RewarderType.BribeRewarder, token, pool)); emit BribeRewarderCreated(RewarderType.BribeRewarder, token, pool, rewarder); } /** * Claim rewards for given rewarders * @param rewarders rewarders to claim * @param account account */ function claimBribeRewards(IBribeRewarder[] memory rewarders, address account) external { for (uint256 i; i < rewarders.length; ++i) { rewarders[i].claim(account); } } /** * @dev Sets the rewarder implementation for the given rewarder type. * Only the owner can call this function. * @param rewarderType The rewarder type. * @param implementation The rewarder implementation. */ function setRewarderImplementation(RewarderType rewarderType, IRewarder implementation) external onlyOwner { _setRewarderImplementation(rewarderType, implementation); } /** * @dev Set token with their minBribeAmounts for whitelist * Notice: For whitelist native rewards, use address(0) * * @param tokens token addresses * @param minBribeAmounts minAmounts to bribe, 0 means token will be 'delisted' */ function setWhitelist(address[] calldata tokens, uint256[] calldata minBribeAmounts) external onlyOwner { uint256 length = tokens.length; if (length != minBribeAmounts.length) revert RewarderFactory__InvalidLength(); for (uint256 i; i < length; ++i) { _whitelistedTokens[tokens[i]] = minBribeAmounts[i]; } } /** * @dev Clone the rewarder implementation for the given rewarder type and initialize it. * @param rewarderType The rewarder type. * @param token The token to reward. * @param pid The pool ID. * @return rewarder The rewarder. */ function _clone(RewarderType rewarderType, IERC20 token, uint256 pid) private returns (IBaseRewarder rewarder) { if (rewarderType == RewarderType.InvalidRewarder) revert RewarderFactory__InvalidRewarderType(); IRewarder implementation = _implementations[rewarderType]; if (address(implementation) == address(0)) revert RewarderFactory__ZeroAddress(); IRewarder[] storage rewarders = _rewarders[rewarderType]; bytes memory immutableData = abi.encodePacked(token, pid); bytes32 salt = keccak256(abi.encodePacked(msg.sender, _nonces[msg.sender]++)); rewarder = IBaseRewarder(ImmutableClone.cloneDeterministic(address(implementation), immutableData, salt)); rewarders.push(rewarder); _rewarderTypes[rewarder] = rewarderType; rewarder.initialize(msg.sender); } function _cloneBribe(RewarderType rewarderType, IERC20 token, address pool) private returns (IBribeRewarder rewarder) { if (rewarderType != RewarderType.BribeRewarder) revert RewarderFactory__InvalidRewarderType(); IRewarder implementation = _implementations[rewarderType]; if (address(implementation) == address(0)) revert RewarderFactory__ZeroAddress(); IRewarder[] storage rewarders = _rewarders[rewarderType]; bytes memory immutableData = abi.encodePacked(token, pool); bytes32 salt = keccak256(abi.encodePacked(msg.sender, _nonces[msg.sender]++)); rewarder = IBribeRewarder(ImmutableClone.cloneDeterministic(address(implementation), immutableData, salt)); rewarders.push(rewarder); _rewarderTypes[rewarder] = rewarderType; rewarder.initialize(msg.sender); } /** * @dev Sets the rewarder implementation for the given rewarder type. * @param rewarderType The rewarder type. * @param implementation The rewarder implementation. */ function _setRewarderImplementation(RewarderType rewarderType, IRewarder implementation) private { if (rewarderType == RewarderType.InvalidRewarder) revert RewarderFactory__InvalidRewarderType(); _implementations[rewarderType] = implementation; emit RewarderImplementationSet(rewarderType, implementation); } /** * returns true if token is whitelisted (min amount > 0) * @param token token */ function _checkWhitelist(address token) private view { if ( _whitelistedTokens[token] == 0) { revert RewarderFactory__TokenNotWhitelisted(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol) pragma solidity ^0.8.20; import {OwnableUpgradeable} from "./OwnableUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is specified at deployment time in the constructor for `Ownable`. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable2Step struct Ownable2StepStorage { address _pendingOwner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable2Step")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant Ownable2StepStorageLocation = 0x237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00; function _getOwnable2StepStorage() private pure returns (Ownable2StepStorage storage $) { assembly { $.slot := Ownable2StepStorageLocation } } event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); function __Ownable2Step_init() internal onlyInitializing { } function __Ownable2Step_init_unchained() internal onlyInitializing { } /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); return $._pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); $._pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); delete $._pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /** * @title Liquidity Book Immutable Clone Library * @notice Minimal immutable proxy library. * @author Trader Joe * @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol) * @author Minimal proxy by 0age (https://github.com/0age) * @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie * (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args) * @dev Minimal proxy: * Although the sw0nt pattern saves 5 gas over the erc-1167 pattern during runtime, * it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern, * which saves 4 gas over the erc-1167 pattern during runtime, and has the smallest bytecode. * @dev Clones with immutable args (CWIA): * The implementation of CWIA here doesn't implements a `receive()` as it is not needed for LB. */ library ImmutableClone { error DeploymentFailed(); error PackedDataTooBig(); /** * @dev Deploys a deterministic clone of `implementation` using immutable arguments encoded in `data`, with `salt` * @param implementation The address of the implementation * @param data The encoded immutable arguments * @param salt The salt */ function cloneDeterministic(address implementation, bytes memory data, bytes32 salt) internal returns (address instance) { assembly { // Compute the boundaries of the data and cache the memory slots around it. let mBefore2 := mload(sub(data, 0x40)) let mBefore1 := mload(sub(data, 0x20)) let dataLength := mload(data) let dataEnd := add(add(data, 0x20), dataLength) let mAfter1 := mload(dataEnd) // +2 bytes for telling how much data there is appended to the call. let extraLength := add(dataLength, 2) // The `creationSize` is `extraLength + 63` // The `runSize` is `creationSize - 10`. // if `extraLength` is greater than `0xffca` revert as the `creationSize` would be greater than `0xffff`. if gt(extraLength, 0xffca) { // Store the function selector of `PackedDataTooBig()`. mstore(0x00, 0xc8c78139) // Revert with (offset, size). revert(0x1c, 0x04) } /** * ---------------------------------------------------------------------------------------------------+ * CREATION (10 bytes) | * ---------------------------------------------------------------------------------------------------| * Opcode | Mnemonic | Stack | Memory | * ---------------------------------------------------------------------------------------------------| * 61 runSize | PUSH2 runSize | r | | * 3d | RETURNDATASIZE | 0 r | | * 81 | DUP2 | r 0 r | | * 60 offset | PUSH1 offset | o r 0 r | | * 3d | RETURNDATASIZE | 0 o r 0 r | | * 39 | CODECOPY | 0 r | [0..runSize): runtime code | * f3 | RETURN | | [0..runSize): runtime code | * ---------------------------------------------------------------------------------------------------| * RUNTIME (98 bytes + extraLength) | * ---------------------------------------------------------------------------------------------------| * Opcode | Mnemonic | Stack | Memory | * ---------------------------------------------------------------------------------------------------| * | * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 36 | CALLDATASIZE | cds | | * 3d | RETURNDATASIZE | 0 cds | | * 3d | RETURNDATASIZE | 0 0 cds | | * 37 | CALLDATACOPY | | [0..cds): calldata | * | * ::: keep some values in stack :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 3d | RETURNDATASIZE | 0 | [0..cds): calldata | * 3d | RETURNDATASIZE | 0 0 | [0..cds): calldata | * 3d | RETURNDATASIZE | 0 0 0 | [0..cds): calldata | * 3d | RETURNDATASIZE | 0 0 0 0 | [0..cds): calldata | * 61 extra | PUSH2 extra | e 0 0 0 0 | [0..cds): calldata | * | * ::: copy extra data to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 80 | DUP1 | e e 0 0 0 0 | [0..cds): calldata | * 60 0x35 | PUSH1 0x35 | 0x35 e e 0 0 0 0 | [0..cds): calldata | * 36 | CALLDATASIZE | cds 0x35 e e 0 0 0 0 | [0..cds): calldata | * 39 | CODECOPY | e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * | * ::: delegate call to the implementation contract ::::::::::::::::::::::::::::::::::::::::::::::::: | * 36 | CALLDATASIZE | cds e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 01 | ADD | cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 3d | RETURNDATASIZE | 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 73 addr | PUSH20 addr | addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 5a | GAS | gas addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * | * ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData | * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData | * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata | * | * 60 0x33 | PUSH1 0x33 | 0x33 success 0 rds | [0..rds): returndata | * 57 | JUMPI | 0 rds | [0..rds): returndata | * | * ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * fd | REVERT | | [0..rds): returndata | * | * ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 5b | JUMPDEST | 0 rds | [0..rds): returndata | * f3 | RETURN | | [0..rds): returndata | * ---------------------------------------------------------------------------------------------------+ */ // Write the bytecode before the data. mstore(data, 0x5af43d3d93803e603357fd5bf3) // Write the address of the implementation. mstore(sub(data, 0x0d), implementation) mstore( sub(data, 0x21), or( shl(0xd8, add(extraLength, 0x35)), or(shl(0x48, extraLength), 0x6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d73) ) ) mstore(dataEnd, shl(0xf0, extraLength)) // Create the instance. instance := create2(0, sub(data, 0x1f), add(extraLength, 0x3f), salt) // If `instance` is zero, revert. if iszero(instance) { // Store the function selector of `DeploymentFailed()`. mstore(0x00, 0x30116425) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the overwritten memory surrounding `data`. mstore(dataEnd, mAfter1) mstore(data, dataLength) mstore(sub(data, 0x20), mBefore1) mstore(sub(data, 0x40), mBefore2) } } /** * @dev Returns the initialization code hash of the clone of `implementation` * using immutable arguments encoded in `data`. * Used for mining vanity addresses with create2crunch. * @param implementation The address of the implementation contract. * @param data The encoded immutable arguments. * @return hash The initialization code hash. */ function initCodeHash(address implementation, bytes memory data) internal pure returns (bytes32 hash) { assembly { // Compute the boundaries of the data and cache the memory slots around it. let mBefore2 := mload(sub(data, 0x40)) let mBefore1 := mload(sub(data, 0x20)) let dataLength := mload(data) let dataEnd := add(add(data, 0x20), dataLength) let mAfter1 := mload(dataEnd) // +2 bytes for telling how much data there is appended to the call. let extraLength := add(dataLength, 2) // The `creationSize` is `extraLength + 63` // The `runSize` is `creationSize - 10`. // if `extraLength` is greater than `0xffca` revert as the `creationSize` would be greater than `0xffff`. if gt(extraLength, 0xffca) { // Store the function selector of `PackedDataTooBig()`. mstore(0x00, 0xc8c78139) // Revert with (offset, size). revert(0x1c, 0x04) } // Write the bytecode before the data. mstore(data, 0x5af43d3d93803e603357fd5bf3) // Write the address of the implementation. mstore(sub(data, 0x0d), implementation) mstore( sub(data, 0x21), or( shl(0xd8, add(extraLength, 0x35)), or(shl(0x48, extraLength), 0x6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d73) ) ) mstore(dataEnd, shl(0xf0, extraLength)) // Create the instance. hash := keccak256(sub(data, 0x1f), add(extraLength, 0x3f)) // Restore the overwritten memory surrounding `data`. mstore(dataEnd, mAfter1) mstore(data, dataLength) mstore(sub(data, 0x20), mBefore1) mstore(sub(data, 0x40), mBefore2) } } /** * @dev Returns the address of the deterministic clone of * `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`. * @param implementation The address of the implementation. * @param data The immutable arguments of the implementation. * @param salt The salt used to compute the address. * @param deployer The address of the deployer. * @return predicted The predicted address. */ function predictDeterministicAddress(address implementation, bytes memory data, bytes32 salt, address deployer) internal pure returns (address predicted) { bytes32 hash = initCodeHash(implementation, data); predicted = predictDeterministicAddress(hash, salt, deployer); } /** * @dev Returns the address when a contract with initialization code hash, * `hash`, is deployed with `salt`, by `deployer`. * @param hash The initialization code hash. * @param salt The salt used to compute the address. * @param deployer The address of the deployer. * @return predicted The predicted address. */ function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer) internal pure returns (address predicted) { /// @solidity memory-safe-assembly assembly { // Compute the boundaries of the data and cache the memory slots around it. let mBefore := mload(0x35) // Compute and store the bytecode hash. mstore8(0x00, 0xff) // Write the prefix. mstore(0x35, hash) mstore(0x01, shl(96, deployer)) mstore(0x15, salt) predicted := keccak256(0x00, 0x55) // Restore the part of the free memory pointer that has been overwritten. mstore(0x35, mBefore) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; interface IRewarder { function getToken() external view returns (IERC20); function getCaller() external view returns (address); function initialize(address initialOwner) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; import {IRewarder} from "./IRewarder.sol"; interface IBribeRewarder is IRewarder { error BribeRewarder__OnlyVoter(); error BribeRewarder__InsufficientFunds(); error BribeRewarder__WrongStartId(); error BribeRewarder__WrongEndId(); error BribeRewarder__ZeroReward(); error BribeRewarder__NativeTransferFailed(); error BribeRewarder__NotOwner(); error BribeRewarder__CannotRenounceOwnership(); error BribeRewarder__NotNativeRewarder(); error BribeRewarder__AlreadyInitialized(); error BribeRewarder__PeriodNotFound(); error BribeRewarder__AmountTooLow(); error BribeRewarder__OnlyVoterAdmin(); event Claimed(address indexed account, address indexed pool, uint256 amount); event Deposited(uint256 indexed periodId, address indexed account, address indexed pool, uint256 amount); event BribeInit(uint256 indexed startId, uint256 indexed lastId, uint256 amountPerPeriod); event Swept(IERC20 indexed token, address indexed account, uint256 amount); function bribe(uint256 startId, uint256 lastId, uint256 amountPerPeriod) external; function claim(address account) external; function deposit(uint256 periodId, address account, uint256 deltaAmount) external; function getPool() external view returns (address); function getPendingReward(address account) external view returns (uint256); function getBribePeriods() external view returns (address pool, uint256[] memory); function getStartVotingPeriodId() external view returns (uint256); function getLastVotingPeriodId() external view returns (uint256); function getAmountPerPeriod() external view returns (uint256); function sweep(IERC20 token, address account) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; import {IRewarder} from "./IRewarder.sol"; interface IBaseRewarder is IRewarder { error BaseRewarder__NativeTransferFailed(); error BaseRewarder__InvalidCaller(); error BaseRewarder__Stopped(); error BaseRewarder__AlreadyStopped(); error BaseRewarder__NotNativeRewarder(); error BaseRewarder__ZeroAmount(); error BaseRewarder__ZeroReward(); error BaseRewarder__InvalidDuration(); error BaseRewarder__InvalidPid(uint256 pid); error BaseRewarder__InvalidStartTimestamp(uint256 startTimestamp); error BaseRewarder__CannotRenounceOwnership(); event Claim(address indexed account, IERC20 indexed token, uint256 reward); event RewardParameterUpdated(uint256 rewardPerSecond, uint256 startTimestamp, uint256 endTimestamp); event Stopped(); event Swept(IERC20 indexed token, address indexed account, uint256 amount); function getToken() external view returns (IERC20); function getCaller() external view returns (address); function getPid() external view returns (uint256); function getRewarderParameter() external view returns (IERC20 token, uint256 rewardPerSecond, uint256 lastUpdateTimestamp, uint256 endTimestamp); function getRemainingReward() external view returns (uint256); function getPendingReward(address account, uint256 balance, uint256 totalSupply) external view returns (IERC20 token, uint256 pendingReward); function isStopped() external view returns (bool); function initialize(address initialOwner) external; function setRewardPerSecond(uint256 maxRewardPerSecond, uint256 expectedDuration) external returns (uint256 rewardPerSecond); function setRewarderParameters(uint256 maxRewardPerSecond, uint256 startTimestamp, uint256 expectedDuration) external returns (uint256 rewardPerSecond); function stop() external; function sweep(IERC20 token, address account) external; function onModify(address account, uint256 pid, uint256 oldBalance, uint256 newBalance, uint256 totalSupply) external returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; import {IRewarder} from "../interfaces/IRewarder.sol"; import {IBribeRewarder} from "../interfaces/IBribeRewarder.sol"; import {IBaseRewarder} from "../interfaces/IBaseRewarder.sol"; interface IRewarderFactory { error RewarderFactory__ZeroAddress(); error RewarderFactory__InvalidRewarderType(); error RewarderFactory__InvalidPid(); error RewarderFactory__TokenNotWhitelisted(); error RewarderFactory__InvalidLength(); enum RewarderType { InvalidRewarder, MasterChefRewarder, BribeRewarder } event RewarderCreated( RewarderType indexed rewarderType, IERC20 indexed token, uint256 indexed pid, IBaseRewarder rewarder ); event BribeRewarderCreated( RewarderType indexed rewarderType, IERC20 indexed token, address indexed pool, IBribeRewarder rewarder ); event RewarderImplementationSet(RewarderType indexed rewarderType, IRewarder indexed implementation); function getBribeCreatorFee() external view returns (uint256); function getWhitelistedTokenInfo (address token) external view returns (bool, uint256); function getRewarderImplementation(RewarderType rewarderType) external view returns (IRewarder); function getRewarderCount(RewarderType rewarderType) external view returns (uint256); function getRewarderAt(RewarderType rewarderType, uint256 index) external view returns (IRewarder); function getRewarderType(IRewarder rewarder) external view returns (RewarderType); function setRewarderImplementation(RewarderType rewarderType, IRewarder implementation) external; function createRewarder(RewarderType rewarderType, IERC20 token, uint256 pid) external returns (IBaseRewarder); function createBribeRewarder(IERC20 token, address pool) external returns (IBribeRewarder); function setWhitelist(address[] calldata tokens, uint256[] calldata minBribeAmounts) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "openzeppelin/=lib/openzeppelin-contracts/contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "solmate/=lib/solmate/", "joe-v2/=lib/joe-v2/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 800 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"RewarderFactory__InvalidLength","type":"error"},{"inputs":[],"name":"RewarderFactory__InvalidPid","type":"error"},{"inputs":[],"name":"RewarderFactory__InvalidRewarderType","type":"error"},{"inputs":[],"name":"RewarderFactory__TokenNotWhitelisted","type":"error"},{"inputs":[],"name":"RewarderFactory__ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum IRewarderFactory.RewarderType","name":"rewarderType","type":"uint8"},{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"contract IBribeRewarder","name":"rewarder","type":"address"}],"name":"BribeRewarderCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum IRewarderFactory.RewarderType","name":"rewarderType","type":"uint8"},{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"contract IBaseRewarder","name":"rewarder","type":"address"}],"name":"RewarderCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum IRewarderFactory.RewarderType","name":"rewarderType","type":"uint8"},{"indexed":true,"internalType":"contract IRewarder","name":"implementation","type":"address"}],"name":"RewarderImplementationSet","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IBribeRewarder[]","name":"rewarders","type":"address[]"},{"internalType":"address","name":"account","type":"address"}],"name":"claimBribeRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"pool","type":"address"}],"name":"createBribeRewarder","outputs":[{"internalType":"contract IBribeRewarder","name":"rewarder","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IRewarderFactory.RewarderType","name":"rewarderType","type":"uint8"},{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"pid","type":"uint256"}],"name":"createRewarder","outputs":[{"internalType":"contract IBaseRewarder","name":"rewarder","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBribeCreatorFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IRewarderFactory.RewarderType","name":"rewarderType","type":"uint8"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRewarderAt","outputs":[{"internalType":"contract IRewarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IRewarderFactory.RewarderType","name":"rewarderType","type":"uint8"}],"name":"getRewarderCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IRewarderFactory.RewarderType","name":"rewarderType","type":"uint8"}],"name":"getRewarderImplementation","outputs":[{"internalType":"contract IRewarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IRewarder","name":"rewarder","type":"address"}],"name":"getRewarderType","outputs":[{"internalType":"enum IRewarderFactory.RewarderType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getWhitelistedTokenInfo","outputs":[{"internalType":"bool","name":"isWhitelisted","type":"bool"},{"internalType":"uint256","name":"minBribeAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"enum IRewarderFactory.RewarderType[]","name":"initialRewarderTypes","type":"uint8[]"},{"internalType":"contract IRewarder[]","name":"initialRewarders","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IRewarderFactory.RewarderType","name":"rewarderType","type":"uint8"},{"internalType":"contract IRewarder","name":"implementation","type":"address"}],"name":"setRewarderImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"minBribeAmounts","type":"uint256[]"}],"name":"setWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061001961001e565b6100d0565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161561006e5760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100cd5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b611334806100df6000396000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c8063a996497a116100b2578063cdffa53811610081578063e6300a0311610066578063e6300a0314610276578063f013e0e114610289578063f2fde38b1461029c57600080fd5b8063cdffa5381461025b578063e30c39781461026e57600080fd5b8063a996497a1461021a578063b12d1f151461022d578063bf64890814610235578063cd2351781461024857600080fd5b806379ba5097116100ee57806379ba50971461018e5780638da5cb5b146101965780639e9dccb61461019e578063a1f4e520146101d757600080fd5b806316bc54b3146101205780633628896a14610150578063715018a61461017157806372bdf2441461017b575b600080fd5b61013361012e366004610f53565b6102af565b6040516001600160a01b0390911681526020015b60405180910390f35b61016361015e366004610f92565b610358565b604051908152602001610147565b610179610398565b005b610133610189366004610fb4565b6103ac565b610179610410565b61013361045d565b6101ca6101ac366004610fde565b6001600160a01b031660009081526002602052604090205460ff1690565b6040516101479190611011565b6102036101e5366004610fde565b6001600160a01b031660009081526004602052604090205480151591565b604080519215158352602083019190915201610147565b610133610228366004611044565b610492565b600554610163565b610179610243366004611093565b6104fd565b610133610256366004610f92565b610598565b61017961026936600461116a565b6105e0565b6101336105f6565b6101796102843660046111d2565b61061f565b610179610297366004611255565b61078b565b6101796102aa366004610fde565b610835565b60006102b96108ba565b60028460028111156102cd576102cd610ffb565b036102eb5760405163dac76ec560e01b815260040160405180910390fd5b6102f68484846108ec565b905081836001600160a01b031685600281111561031557610315610ffb565b6040516001600160a01b03851681527f9f6902c2aefd6fe22828245dde3226eb65e7633ffcdee0e32948a4e541f91dd89060200160405180910390a49392505050565b60006001600083600281111561037057610370610ffb565b600281111561038157610381610ffb565b815260208101919091526040016000205492915050565b6103a06108ba565b6103aa6000610b32565b565b6000600160008460028111156103c4576103c4610ffb565b60028111156103d5576103d5610ffb565b815260200190815260200160002082815481106103f4576103f46112c1565b6000918252602090912001546001600160a01b03169392505050565b338061041a6105f6565b6001600160a01b0316146104515760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b61045a81610b32565b50565b6000807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005b546001600160a01b031692915050565b600061049d83610b6a565b6104a960028484610ba2565b90506001600160a01b0380831690841660026040516001600160a01b03851681527f8720b0e0ebbdf235fd5fdf990b15909a4c1679b3df2172155bfd4a719f2301d99060200160405180910390a492915050565b60005b82518110156105935782818151811061051b5761051b6112c1565b6020908102919091010151604051630f41a04d60e11b81526001600160a01b03848116600483015290911690631e83409a90602401600060405180830381600087803b15801561056a57600080fd5b505af115801561057e573d6000803e3d6000fd5b505050508061058c906112d7565b9050610500565b505050565b60008060008360028111156105af576105af610ffb565b60028111156105c0576105c0610ffb565b81526020810191909152604001600020546001600160a01b031692915050565b6105e86108ba565b6105f28282610ca9565b5050565b6000807f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00610482565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0080546001919068010000000000000000900460ff168061066e5750805467ffffffffffffffff808416911610155b1561068c5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617680100000000000000001781556106bc87610d6d565b8460005b8181101561072e5761071e8888838181106106dd576106dd6112c1565b90506020020160208101906106f29190610f92565b878784818110610704576107046112c1565b90506020020160208101906107199190610fde565b610ca9565b610727816112d7565b90506106c0565b50506000600555805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a150505050505050565b6107936108ba565b828181146107b457604051633b61d77560e01b815260040160405180910390fd5b60005b8181101561082d578383828181106107d1576107d16112c1565b90506020020135600460008888858181106107ee576107ee6112c1565b90506020020160208101906108039190610fde565b6001600160a01b03168152602081019190915260400160002055610826816112d7565b90506107b7565b505050505050565b61083d6108ba565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c0080546001600160a01b0319166001600160a01b038316908117825561088161045d565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a35050565b336108c361045d565b6001600160a01b0316146103aa5760405163118cdaa760e01b8152336004820152602401610448565b60008084600281111561090157610901610ffb565b0361091f5760405163dac76ec560e01b815260040160405180910390fd5b600080600086600281111561093657610936610ffb565b600281111561094757610947610ffb565b81526020810191909152604001600020546001600160a01b031690508061098157604051632aabcc1360e01b815260040160405180910390fd5b60006001600087600281111561099957610999610ffb565b60028111156109aa576109aa610ffb565b81526020019081526020016000209050600085856040516020016109ec92919060609290921b6bffffffffffffffffffffffff19168252601482015260340190565b60408051601f19818403018152918152336000818152600360205291822080549394509192909183610a1d836112d7565b9091555060405160609290921b6bffffffffffffffffffffffff191660208301526034820152605401604051602081830303815290604052805190602001209050610a69848383610d7e565b8354600180820186556000868152602080822090930180546001600160a01b0319166001600160a01b03861690811790915581526002928390526040902080549398508b93909260ff1990911691908490811115610ac957610ac9610ffb565b021790555060405163189acdbd60e31b81523360048201526001600160a01b0386169063c4d66de890602401600060405180830381600087803b158015610b0f57600080fd5b505af1158015610b23573d6000803e3d6000fd5b50505050505050509392505050565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c0080546001600160a01b03191681556105f282610e39565b6001600160a01b038116600090815260046020526040812054900361045a57604051630685823560e51b815260040160405180910390fd5b60006002846002811115610bb857610bb8610ffb565b14610bd65760405163dac76ec560e01b815260040160405180910390fd5b6000806000866002811115610bed57610bed610ffb565b6002811115610bfe57610bfe610ffb565b81526020810191909152604001600020546001600160a01b0316905080610c3857604051632aabcc1360e01b815260040160405180910390fd5b600060016000876002811115610c5057610c50610ffb565b6002811115610c6157610c61610ffb565b81526020019081526020016000209050600085856040516020016109ec929190606092831b6bffffffffffffffffffffffff1990811682529190921b16601482015260280190565b6000826002811115610cbd57610cbd610ffb565b03610cdb5760405163dac76ec560e01b815260040160405180910390fd5b80600080846002811115610cf157610cf1610ffb565b6002811115610d0257610d02610ffb565b8152602081019190915260400160002080546001600160a01b0319166001600160a01b039283161790558116826002811115610d4057610d40610ffb565b6040517fe6f4086f57b7e875a8858b8ecc873e8dfcf686d42d08de2a31d38d403c2b07e490600090a35050565b610d75610eaa565b61045a81610ef8565b600060408303516020840351845180602087010180516002830161ffca811115610db05763c8c781396000526004601cfd5b6c5af43d3d93803e603357fd5bf3895289600d8a03527d6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d738160481b176035820160d81b1760218a03528060f01b835287603f8201601f8b036000f596505085610e1f5763301164256000526004601cfd5b90528552601f19850152603f199093019290925250919050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166103aa57604051631afcd79f60e31b815260040160405180910390fd5b610f00610eaa565b6001600160a01b03811661045157604051631e4fbdf760e01b815260006004820152602401610448565b803560038110610f3957600080fd5b919050565b6001600160a01b038116811461045a57600080fd5b600080600060608486031215610f6857600080fd5b610f7184610f2a565b92506020840135610f8181610f3e565b929592945050506040919091013590565b600060208284031215610fa457600080fd5b610fad82610f2a565b9392505050565b60008060408385031215610fc757600080fd5b610fd083610f2a565b946020939093013593505050565b600060208284031215610ff057600080fd5b8135610fad81610f3e565b634e487b7160e01b600052602160045260246000fd5b602081016003831061103357634e487b7160e01b600052602160045260246000fd5b91905290565b8035610f3981610f3e565b6000806040838503121561105757600080fd5b823561106281610f3e565b9150602083013561107281610f3e565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156110a657600080fd5b823567ffffffffffffffff808211156110be57600080fd5b818501915085601f8301126110d257600080fd5b81356020828211156110e6576110e661107d565b8160051b604051601f19603f8301168101818110868211171561110b5761110b61107d565b60405292835281830193508481018201928984111561112957600080fd5b948201945b8386101561114e5761113f86611039565b8552948201949382019361112e565b965061115d9050878201611039565b9450505050509250929050565b6000806040838503121561117d57600080fd5b61106283610f2a565b60008083601f84011261119857600080fd5b50813567ffffffffffffffff8111156111b057600080fd5b6020830191508360208260051b85010111156111cb57600080fd5b9250929050565b6000806000806000606086880312156111ea57600080fd5b85356111f581610f3e565b9450602086013567ffffffffffffffff8082111561121257600080fd5b61121e89838a01611186565b9096509450604088013591508082111561123757600080fd5b5061124488828901611186565b969995985093965092949392505050565b6000806000806040858703121561126b57600080fd5b843567ffffffffffffffff8082111561128357600080fd5b61128f88838901611186565b909650945060208701359150808211156112a857600080fd5b506112b587828801611186565b95989497509550505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016112f757634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220bde4eace8c67524748715778cbbac4c80348af5a732622f6933c46630c41055064736f6c63430008140033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061011b5760003560e01c8063a996497a116100b2578063cdffa53811610081578063e6300a0311610066578063e6300a0314610276578063f013e0e114610289578063f2fde38b1461029c57600080fd5b8063cdffa5381461025b578063e30c39781461026e57600080fd5b8063a996497a1461021a578063b12d1f151461022d578063bf64890814610235578063cd2351781461024857600080fd5b806379ba5097116100ee57806379ba50971461018e5780638da5cb5b146101965780639e9dccb61461019e578063a1f4e520146101d757600080fd5b806316bc54b3146101205780633628896a14610150578063715018a61461017157806372bdf2441461017b575b600080fd5b61013361012e366004610f53565b6102af565b6040516001600160a01b0390911681526020015b60405180910390f35b61016361015e366004610f92565b610358565b604051908152602001610147565b610179610398565b005b610133610189366004610fb4565b6103ac565b610179610410565b61013361045d565b6101ca6101ac366004610fde565b6001600160a01b031660009081526002602052604090205460ff1690565b6040516101479190611011565b6102036101e5366004610fde565b6001600160a01b031660009081526004602052604090205480151591565b604080519215158352602083019190915201610147565b610133610228366004611044565b610492565b600554610163565b610179610243366004611093565b6104fd565b610133610256366004610f92565b610598565b61017961026936600461116a565b6105e0565b6101336105f6565b6101796102843660046111d2565b61061f565b610179610297366004611255565b61078b565b6101796102aa366004610fde565b610835565b60006102b96108ba565b60028460028111156102cd576102cd610ffb565b036102eb5760405163dac76ec560e01b815260040160405180910390fd5b6102f68484846108ec565b905081836001600160a01b031685600281111561031557610315610ffb565b6040516001600160a01b03851681527f9f6902c2aefd6fe22828245dde3226eb65e7633ffcdee0e32948a4e541f91dd89060200160405180910390a49392505050565b60006001600083600281111561037057610370610ffb565b600281111561038157610381610ffb565b815260208101919091526040016000205492915050565b6103a06108ba565b6103aa6000610b32565b565b6000600160008460028111156103c4576103c4610ffb565b60028111156103d5576103d5610ffb565b815260200190815260200160002082815481106103f4576103f46112c1565b6000918252602090912001546001600160a01b03169392505050565b338061041a6105f6565b6001600160a01b0316146104515760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b61045a81610b32565b50565b6000807f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005b546001600160a01b031692915050565b600061049d83610b6a565b6104a960028484610ba2565b90506001600160a01b0380831690841660026040516001600160a01b03851681527f8720b0e0ebbdf235fd5fdf990b15909a4c1679b3df2172155bfd4a719f2301d99060200160405180910390a492915050565b60005b82518110156105935782818151811061051b5761051b6112c1565b6020908102919091010151604051630f41a04d60e11b81526001600160a01b03848116600483015290911690631e83409a90602401600060405180830381600087803b15801561056a57600080fd5b505af115801561057e573d6000803e3d6000fd5b505050508061058c906112d7565b9050610500565b505050565b60008060008360028111156105af576105af610ffb565b60028111156105c0576105c0610ffb565b81526020810191909152604001600020546001600160a01b031692915050565b6105e86108ba565b6105f28282610ca9565b5050565b6000807f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00610482565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0080546001919068010000000000000000900460ff168061066e5750805467ffffffffffffffff808416911610155b1561068c5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff191667ffffffffffffffff831617680100000000000000001781556106bc87610d6d565b8460005b8181101561072e5761071e8888838181106106dd576106dd6112c1565b90506020020160208101906106f29190610f92565b878784818110610704576107046112c1565b90506020020160208101906107199190610fde565b610ca9565b610727816112d7565b90506106c0565b50506000600555805468ff00000000000000001916815560405167ffffffffffffffff831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a150505050505050565b6107936108ba565b828181146107b457604051633b61d77560e01b815260040160405180910390fd5b60005b8181101561082d578383828181106107d1576107d16112c1565b90506020020135600460008888858181106107ee576107ee6112c1565b90506020020160208101906108039190610fde565b6001600160a01b03168152602081019190915260400160002055610826816112d7565b90506107b7565b505050505050565b61083d6108ba565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c0080546001600160a01b0319166001600160a01b038316908117825561088161045d565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a35050565b336108c361045d565b6001600160a01b0316146103aa5760405163118cdaa760e01b8152336004820152602401610448565b60008084600281111561090157610901610ffb565b0361091f5760405163dac76ec560e01b815260040160405180910390fd5b600080600086600281111561093657610936610ffb565b600281111561094757610947610ffb565b81526020810191909152604001600020546001600160a01b031690508061098157604051632aabcc1360e01b815260040160405180910390fd5b60006001600087600281111561099957610999610ffb565b60028111156109aa576109aa610ffb565b81526020019081526020016000209050600085856040516020016109ec92919060609290921b6bffffffffffffffffffffffff19168252601482015260340190565b60408051601f19818403018152918152336000818152600360205291822080549394509192909183610a1d836112d7565b9091555060405160609290921b6bffffffffffffffffffffffff191660208301526034820152605401604051602081830303815290604052805190602001209050610a69848383610d7e565b8354600180820186556000868152602080822090930180546001600160a01b0319166001600160a01b03861690811790915581526002928390526040902080549398508b93909260ff1990911691908490811115610ac957610ac9610ffb565b021790555060405163189acdbd60e31b81523360048201526001600160a01b0386169063c4d66de890602401600060405180830381600087803b158015610b0f57600080fd5b505af1158015610b23573d6000803e3d6000fd5b50505050505050509392505050565b7f237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c0080546001600160a01b03191681556105f282610e39565b6001600160a01b038116600090815260046020526040812054900361045a57604051630685823560e51b815260040160405180910390fd5b60006002846002811115610bb857610bb8610ffb565b14610bd65760405163dac76ec560e01b815260040160405180910390fd5b6000806000866002811115610bed57610bed610ffb565b6002811115610bfe57610bfe610ffb565b81526020810191909152604001600020546001600160a01b0316905080610c3857604051632aabcc1360e01b815260040160405180910390fd5b600060016000876002811115610c5057610c50610ffb565b6002811115610c6157610c61610ffb565b81526020019081526020016000209050600085856040516020016109ec929190606092831b6bffffffffffffffffffffffff1990811682529190921b16601482015260280190565b6000826002811115610cbd57610cbd610ffb565b03610cdb5760405163dac76ec560e01b815260040160405180910390fd5b80600080846002811115610cf157610cf1610ffb565b6002811115610d0257610d02610ffb565b8152602081019190915260400160002080546001600160a01b0319166001600160a01b039283161790558116826002811115610d4057610d40610ffb565b6040517fe6f4086f57b7e875a8858b8ecc873e8dfcf686d42d08de2a31d38d403c2b07e490600090a35050565b610d75610eaa565b61045a81610ef8565b600060408303516020840351845180602087010180516002830161ffca811115610db05763c8c781396000526004601cfd5b6c5af43d3d93803e603357fd5bf3895289600d8a03527d6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d738160481b176035820160d81b1760218a03528060f01b835287603f8201601f8b036000f596505085610e1f5763301164256000526004601cfd5b90528552601f19850152603f199093019290925250919050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166103aa57604051631afcd79f60e31b815260040160405180910390fd5b610f00610eaa565b6001600160a01b03811661045157604051631e4fbdf760e01b815260006004820152602401610448565b803560038110610f3957600080fd5b919050565b6001600160a01b038116811461045a57600080fd5b600080600060608486031215610f6857600080fd5b610f7184610f2a565b92506020840135610f8181610f3e565b929592945050506040919091013590565b600060208284031215610fa457600080fd5b610fad82610f2a565b9392505050565b60008060408385031215610fc757600080fd5b610fd083610f2a565b946020939093013593505050565b600060208284031215610ff057600080fd5b8135610fad81610f3e565b634e487b7160e01b600052602160045260246000fd5b602081016003831061103357634e487b7160e01b600052602160045260246000fd5b91905290565b8035610f3981610f3e565b6000806040838503121561105757600080fd5b823561106281610f3e565b9150602083013561107281610f3e565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156110a657600080fd5b823567ffffffffffffffff808211156110be57600080fd5b818501915085601f8301126110d257600080fd5b81356020828211156110e6576110e661107d565b8160051b604051601f19603f8301168101818110868211171561110b5761110b61107d565b60405292835281830193508481018201928984111561112957600080fd5b948201945b8386101561114e5761113f86611039565b8552948201949382019361112e565b965061115d9050878201611039565b9450505050509250929050565b6000806040838503121561117d57600080fd5b61106283610f2a565b60008083601f84011261119857600080fd5b50813567ffffffffffffffff8111156111b057600080fd5b6020830191508360208260051b85010111156111cb57600080fd5b9250929050565b6000806000806000606086880312156111ea57600080fd5b85356111f581610f3e565b9450602086013567ffffffffffffffff8082111561121257600080fd5b61121e89838a01611186565b9096509450604088013591508082111561123757600080fd5b5061124488828901611186565b969995985093965092949392505050565b6000806000806040858703121561126b57600080fd5b843567ffffffffffffffff8082111561128357600080fd5b61128f88838901611186565b909650945060208701359150808211156112a857600080fd5b506112b587828801611186565b95989497509550505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016112f757634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220bde4eace8c67524748715778cbbac4c80348af5a732622f6933c46630c41055064736f6c63430008140033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.