Overview
S Balance
0 S
S Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 53 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Pull All And Cla... | 5990169 | 18 hrs ago | IN | 0 S | 0.0069068 | ||||
Pull All And Cla... | 5679504 | 3 days ago | IN | 0 S | 0.0069068 | ||||
Pull All And Cla... | 5669091 | 3 days ago | IN | 0 S | 0.0069068 | ||||
Pull All And Cla... | 5668553 | 3 days ago | IN | 0 S | 0.0069068 | ||||
Pull All And Cla... | 5668543 | 3 days ago | IN | 0 S | 0.0062228 | ||||
Pull All And Cla... | 5667381 | 3 days ago | IN | 0 S | 0.0075908 | ||||
Pull All And Cla... | 5667328 | 3 days ago | IN | 0 S | 0.004633 | ||||
Pull All And Cla... | 5667321 | 3 days ago | IN | 0 S | 0.0069068 | ||||
Pull All And Cla... | 5667318 | 3 days ago | IN | 0 S | 0.0075908 | ||||
Pull All And Cla... | 5667315 | 3 days ago | IN | 0 S | 0.0075908 | ||||
Pull All And Cla... | 5667306 | 3 days ago | IN | 0 S | 0.00829148 | ||||
Pull All And Cla... | 4981818 | 9 days ago | IN | 0 S | 0.0069068 | ||||
Pull All And Cla... | 4892213 | 10 days ago | IN | 0 S | 0.00690635 | ||||
Pull All And Cla... | 4683798 | 11 days ago | IN | 0 S | 0.00818721 | ||||
Pull All And Cla... | 4653315 | 11 days ago | IN | 0 S | 0.0069068 | ||||
Pull All And Cla... | 4653293 | 11 days ago | IN | 0 S | 0.0062228 | ||||
Pull All And Cla... | 4626891 | 12 days ago | IN | 0 S | 0.0069068 | ||||
Pull All And Cla... | 4626861 | 12 days ago | IN | 0 S | 0.0062228 | ||||
Pull All And Cla... | 4626812 | 12 days ago | IN | 0 S | 0.0062228 | ||||
Pull All And Cla... | 4626759 | 12 days ago | IN | 0 S | 0.0069068 | ||||
Pull All And Cla... | 4626722 | 12 days ago | IN | 0 S | 0.0062228 | ||||
Pull All And Cla... | 4614272 | 12 days ago | IN | 0 S | 0.00679322 | ||||
Pull All And Cla... | 3711829 | 18 days ago | IN | 0 S | 0.00062228 | ||||
Pull All And Cla... | 3670260 | 19 days ago | IN | 0 S | 0.00069068 | ||||
Pull All And Cla... | 3670243 | 19 days ago | IN | 0 S | 0.00069068 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
GeneralTokenDispenserV1
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import {Ownable2Step, Ownable} from "@openzeppelin/contracts/access/Ownable2Step.sol"; import "../../../Lynx/interfaces/ILynxVersionedContract.sol"; import {IPushableDispenserV1} from "../interfaces/IPushableDispenserV1.sol"; import {IDispenserPullSourceV1} from "../interfaces/IDispenserPullSourceV1.sol"; import {TokenHandlingContractUtils} from "../../../Utils/TokenHandlingContractUtils.sol"; import {LexPoolEvents} from "../../../Lynx/interfaces/ILexPoolV1.sol"; import {AbstractPullSourceV1} from "./AbstractPullSourceV1.sol"; /** * @title GeneralTokenDispenserV1 * @notice Functions as a single point for token dispensations from many sources */ contract GeneralTokenDispenserV1 is Ownable2Step, AbstractPullSourceV1, IPushableDispenserV1, ILynxVersionedContract { string public constant CONTRACT_NAME = "GeneralTokenDispenserV1"; string public constant CONTRACT_VERSION = "100"; // 0.1 // ***** Enums ***** enum DispensationPushLevel { NONE, BASE // Can push token dispensation plan but has to provide the tokens in the same tx } // ***** Events ***** event TokenPulledForAccountFromSource( address indexed token, address indexed account, address indexed source, uint256 amount ); event TokenPushedForAccount( string indexed dispensationKey, address indexed token, address indexed account, address pusher, uint256 round, uint256 amount ); event IsAllClaimingPausedFlagSet(bool indexed value); event IsClaimingPausedForTokenFlagSet( address indexed token, bool indexed value ); event PullSourceAdded(address indexed token, address indexed pullSource); event PullSourceRemoved(address indexed token, address indexed pullSource); event PusherRegistered( address indexed _token, address indexed _pusher, DispensationPushLevel level ); event PusherUnregistered(address indexed _token, address indexed _pusher); event DispensationStarted( string indexed dispensationKey, address indexed token ); event DispensationEnded( string indexed dispensationKey, address indexed token ); event DispensationExplained( string indexed dispensationKey, address indexed token, string name, string description ); event TokenAddedToEverDispensed(address indexed token); event TokenAddedToCurrentlyDispensed(address indexed token); event TokenRemovedFromCurrentlyDispensed(address indexed token); // ***** Modifiers ***** modifier onlyRegisteredPusher(address _token, address _pusher) { require(isRegisteredPusher(_token, _pusher), "NOT_REGISTERED_PUSHER"); _; } modifier whenClaimNotPaused(address _token) { require(!isAllClaimingPaused, "ALL_CLAIMING_PAUSED"); require(!isClaimingPausedForToken[_token], "CLAIMING_PAUSED_FOR_TOKEN"); _; } // ***** Storage ***** // Allows to pause all claiming bool public isAllClaimingPaused; // Allows to pause claiming for specific tokens // token => flag mapping(address => bool) public isClaimingPausedForToken; // token => live contracts that can generate distributions events. mapping(address => address[]) public pullSourcesForToken; // token => poolSource => is pull source mapping(address => mapping(address => bool)) public isPullSourceForToken; // token => pushers mapping(address => address[]) public pushersForToken; // token => pusher => level mapping(address => mapping(address => DispensationPushLevel)) public dispensationPusherLevels; address[] public allTokensCurrentlyDispensed; address[] public allTokensEverDispensed; // token => flag mapping(address => bool) public wasTokenEverDispensed; // token => flag mapping(address => bool) public isTokenCurrentlyDispensed; // token => account => historic amount of tokens dispensed to account mapping(address => mapping(address => uint256)) public historicDispensationsForAccount; // token => account => historic amount of tokens dispensed to downstream dispense mapping(address => mapping(address => uint256)) public downstreamDispensationsForAccount; // token => ongoing dispensation keys mapping(address => string[]) public allOngoingDispensationsForToken; // token => dispensation key => flag mapping(address => mapping(string => bool)) public isOngoingDispensation; // token => dispensation key => name mapping(address => mapping(string => string)) public dispensationNames; // token => dispensation key => description mapping(address => mapping(string => string)) public dispensationDescriptions; // ***** Views ***** /** * @notice Returns the name of the contract */ function getContractName() external pure returns (string memory) { return CONTRACT_NAME; } /** * @notice Returns the version of the contract * @dev units are scaled by 1000 (1,000 = 1.00, 1,120 = 1.12) */ function getContractVersion() external pure returns (string memory) { return CONTRACT_VERSION; } function isPushableDispenserV1() external pure returns (bool) { return true; } function getPullSourcesForToken( address _token ) external view returns (address[] memory) { return pullSourcesForToken[_token]; } function getPushersForToken( address _token ) external view returns (address[] memory) { return pushersForToken[_token]; } function getDispensationPusherLevel( address _token, address _pusher ) external view returns (DispensationPushLevel) { return dispensationPusherLevels[_token][_pusher]; } function getDispensationInfo( string calldata dispensationKey, address _token ) external view returns (string memory name, string memory description) { return ( dispensationNames[_token][dispensationKey], dispensationDescriptions[_token][dispensationKey] ); } function getAllTokensEverDispensed() external view returns (address[] memory) { return allTokensEverDispensed; } function getAllTokensCurrentlyDispensed() external view returns (address[] memory) { return allTokensCurrentlyDispensed; } function getAllOngoingDispensationsForToken( address _token ) external view returns (string[] memory) { return allOngoingDispensationsForToken[_token]; } // ***** Constructor ***** constructor() Ownable(msg.sender) {} // ***** Admin Functions ***** function setDownstreamDispenser( address _downstreamDispenser ) external onlyOwner { setDownstreamDispenserInternal(_downstreamDispenser); } function setIsAllClaimingPaused(bool _value) external onlyOwner { // Validity require(isAllClaimingPaused != _value, "ALREADY_SET"); // Storage isAllClaimingPaused = _value; // Event emit IsAllClaimingPausedFlagSet(isAllClaimingPaused); } function setIsClaimingPausedForToken( address _token, bool _value ) external onlyOwner { // Validity require(isClaimingPausedForToken[_token] != _value, "ALREADY_SET"); // Storage isClaimingPausedForToken[_token] = _value; // Event emit IsClaimingPausedForTokenFlagSet( _token, isClaimingPausedForToken[_token] ); } function addPullSource( address _token, address _pullSource ) external onlyOwner { // Sanity require( IDispenserPullSourceV1(_pullSource).isDispenserMatchingSourceV1(), "NOT_PULL_SOURCE_V1" ); // Prevent duplications address[] storage pullSources = pullSourcesForToken[_token]; for (uint i = 0; i < pullSources.length; i++) { require(pullSources[i] != _pullSource, "PULL_SOURCE_ALREADY_ADDED"); } // Storage pullSourcesForToken[_token].push(_pullSource); isPullSourceForToken[_token][_pullSource] = true; // Internal registry addTokenToListsIfNeeded(_token); // Event emit PullSourceAdded(_token, _pullSource); } function removePullSource( address _token, address _pullSource ) external onlyOwner { bool pullSourceFound = false; // Storage address[] storage pullSources = pullSourcesForToken[_token]; for (uint i = 0; i < pullSources.length; i++) { if (pullSources[i] == _pullSource) { pullSources[i] = pullSources[pullSources.length - 1]; pullSources.pop(); pullSourceFound = true; break; } } // Sanity require(pullSourceFound, "PULL_SOURCE_NOT_FOUND"); // Storage isPullSourceForToken[_token][_pullSource] = false; // Internal registry removeTokenFromListsIfNeeded(_token); // Event emit PullSourceRemoved(_token, _pullSource); } function registerPusher( address _token, address _pusher, DispensationPushLevel level ) external onlyOwner { // Validation require(!isRegisteredPusher(_token, _pusher), "PUSHER_ALREADY_REGISTERED"); require(level != DispensationPushLevel.NONE, "CANNOT_REGISTER_NONE_LEVEL"); // Storage dispensationPusherLevels[_token][_pusher] = level; // Internal registry pushersForToken[_token].push(_pusher); addTokenToListsIfNeeded(_token); // Event emit PusherRegistered(_token, _pusher, level); } function unregisterPusher( address _token, address _pusher ) external onlyOwner { // Validation require(isRegisteredPusher(_token, _pusher), "PUSHER_NOT_REGISTERED"); // Storage dispensationPusherLevels[_token][_pusher] = DispensationPushLevel.NONE; // Remove pusher from array address[] storage pushers = pushersForToken[_token]; for (uint i = 0; i < pushers.length; i++) { if (pushers[i] == _pusher) { pushers[i] = pushers[pushers.length - 1]; pushers.pop(); break; } } // Internal registry removeTokenFromListsIfNeeded(_token); // Event emit PusherUnregistered(_token, _pusher); } function startDispensation( string calldata _dispensationKey, address _token, string calldata _name, string calldata _description ) external onlyOwner { // Validity require( !isOngoingDispensation[_token][_dispensationKey], "ALREADY_ONGOING" ); // Storage isOngoingDispensation[_token][_dispensationKey] = true; allOngoingDispensationsForToken[_token].push(_dispensationKey); explainDispensationInternal(_dispensationKey, _token, _name, _description); // Event emit DispensationStarted(_dispensationKey, _token); } function endDispensation( string calldata _dispensationKey, address _token ) external onlyOwner { // Validity require( isOngoingDispensation[_token][_dispensationKey], "NOT_ONGOING_DISPENSATION" ); // Storage isOngoingDispensation[_token][_dispensationKey] = false; string[] storage ongoingDispensationsForToken = allOngoingDispensationsForToken[ _token ]; for (uint i = 0; i < ongoingDispensationsForToken.length; i++) { if ( keccak256(abi.encodePacked(ongoingDispensationsForToken[i])) == keccak256(abi.encodePacked(_dispensationKey)) ) { ongoingDispensationsForToken[i] = ongoingDispensationsForToken[ ongoingDispensationsForToken.length - 1 ]; ongoingDispensationsForToken.pop(); break; } } explainDispensationInternal(_dispensationKey, _token, "", ""); // Event emit DispensationEnded(_dispensationKey, _token); } function explainDispensation( string calldata _dispensationKey, address _token, string calldata _name, string calldata _description ) external onlyOwner { explainDispensationInternal(_dispensationKey, _token, _name, _description); } /** * @notice Sweep any tokens from the contract * @dev Owner can sweep any token * @param _token The token to sweep * @param _amount The amount to sweep */ function sweepTokens(address _token, uint256 _amount) external onlyOwner { sweepTokensInternal(_token, owner(), _amount); } function discreditAccount( address _token, address _account, uint256 _amount, address _destination ) external onlyOwner { discreditTokenInternal(_token, _account, _amount, _destination); } function discreditAccounts( address _token, address[] calldata _accounts, uint256[] calldata _amounts, address _destination ) external onlyOwner { // Sanity require(_accounts.length == _amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < _accounts.length; i++) { discreditTokenInternal(_token, _accounts[i], _amounts[i], _destination); } } // ***** Dispensation Functions ***** function receiveDispensationPushForAccount( string calldata _dispensationKey, uint256 _dispensationRoundNumber, address _token, address _account, uint256 _amount ) external override { address pusher = msg.sender; // Ensure sender can push dispensation with given key require(isRegisteredPusher(_token, pusher), "PUSHER_NOT_REGISTERED"); // Ensure dispensation is ongoing require( isOngoingDispensation[_token][_dispensationKey], "NOT_ONGOING_DISPENSATION" ); // Sanity require(_amount > 0, "AMOUNT_ZERO"); // Take tokens(if must) takeTokens(_token, msg.sender, _amount); registerDispensationPushForAccountInternal( _dispensationKey, _dispensationRoundNumber, _token, _account, _amount, pusher ); } function receiveDispensationPushForAccounts( string calldata _dispensationKey, uint256 _dispensationRoundNumber, address _token, address[] calldata _accounts, uint256[] calldata _amounts ) external override { require(_accounts.length == _amounts.length, "LENGTH_MISMATCH"); address pusher = msg.sender; // Ensure sender can push dispensation with given key require(isRegisteredPusher(_token, pusher), "PUSHER_NOT_REGISTERED"); // Ensure dispensation is ongoing require( isOngoingDispensation[_token][_dispensationKey], "NOT_ONGOING_DISPENSATION" ); // Calculate total amount uint256 totalAmount = 0; for (uint i = 0; i < _accounts.length; i++) { totalAmount += _amounts[i]; } // Sanity require(totalAmount > 0, "AMOUNT_ZERO"); // Take tokens takeTokens(_token, pusher, totalAmount); // Credit accounts for (uint256 i = 0; i < _accounts.length; i++) { registerDispensationPushForAccountInternal( _dispensationKey, _dispensationRoundNumber, _token, _accounts[i], _amounts[i], pusher ); } } // ***** Claiming Functions ***** /** * @notice Will dispense all pending _token to _account */ function claimTokenFor( address _token, address _account ) external whenClaimNotPaused(_token) { // Dispense dispensePendingTokenToOwnerInternal(_token, _account); } /** * @notice Will pull from all known sources and then dispense all pending _token to _account */ function pullAllAndClaimFor( address _token, address _account ) external whenClaimNotPaused(_token) { // Pull from all sources _pullFromAllSourcesAndRegisterInternal(_token, _account); // Dispense dispensePendingTokenToOwnerInternal(_token, _account); } /** * @notice Will pull from given _pullSources and then dispense all pending _token to _account */ function pullSomeAndClaimFor( address _token, address _account, address[] calldata pullSources ) external whenClaimNotPaused(_token) { require(pullSources.length > 0, "NO_SOURCES_PROVIDED"); // Pull from sources pullFromSomeSourcesAndRegisterInternal(pullSources, _token, _account); // Dispense dispensePendingTokenToOwnerInternal(_token, _account); } // ***** Internal Dispensation Functions ***** /** * @notice Will send all of _account pending _token to _account */ function dispensePendingTokenToOwnerInternal( address _token, address _account ) internal { dispensePendingTokenToReceiverInternal(_token, _account, _account); } /** * @notice Registers the dispensation in the historic records */ function onTokenDispensedToReceiverInternal( address _token, address _account, address _receiver, uint256 amountDispensed ) internal override { if (_account == _receiver) { // Update historic dispensed amount historicDispensationsForAccount[_token][_account] += amountDispensed; } else { // Update downstream dispensed amount downstreamDispensationsForAccount[_token][_account] += amountDispensed; } } // ***** Internal Source Pulling Functions ***** /** * @notice calls 'pullFromSourceAndRegisterInternal' for each listed source for _token */ function _pullFromAllSourcesAndRegisterInternal( address _token, address _account ) internal override returns (uint256 externalPulledAmount) { address[] memory pullSources = pullSourcesForToken[address(_token)]; externalPulledAmount = 0; for (uint i = 0; i < pullSources.length; i++) { externalPulledAmount += pullFromSourceAndRegisterInternal( IDispenserPullSourceV1(pullSources[i]), _token, _account ); } } /** * @notice calls 'pullFromSourceAndRegisterInternal' for each listed source for _token */ function _getExternalPendingAmountForAccountView( address _token, address _account ) internal view override returns (uint256 externalPendingAmount) { address[] memory pullSources = pullSourcesForToken[address(_token)]; externalPendingAmount = 0; for (uint i = 0; i < pullSources.length; i++) { externalPendingAmount += IDispenserPullSourceV1(pullSources[i]) .getPendingAmountForAccountView(_token, _account); } } /** * @notice calls 'pullFromSourceAndRegisterInternal' for each given source */ function pullFromSomeSourcesAndRegisterInternal( address[] calldata _sources, address _token, address _account ) internal { for (uint i = 0; i < _sources.length; i++) { pullFromSourceAndRegisterInternal( IDispenserPullSourceV1(_sources[i]), _token, _account ); } } /** * Pulls from _source and credits gains to _account */ function pullFromSourceAndRegisterInternal( IDispenserPullSourceV1 _source, address _token, address _account ) internal returns (uint256 pulledAmount) { pulledAmount = pullFromSourceInternal(_source, _token, _account); creditTokenInternal(address(_token), _account, pulledAmount); } /** * @notice Pulls tokens from _source for _account * @return pulledAmount The tokens sent to this contract for _account */ function pullFromSourceInternal( IDispenserPullSourceV1 _source, address _token, address _account ) internal returns (uint256 pulledAmount) { // Sanity -- ensuring source is registered require( isPullSourceForToken[address(_token)][address(_source)], "NOT_PULL_SOURCE" ); uint256 balanceBefore = getSelfBalanceInTokenInternal(_token); _source.pullTokenForAccount(address(_token), _account); uint256 balanceAfter = getSelfBalanceInTokenInternal(_token); pulledAmount = balanceAfter - balanceBefore; emit TokenPulledForAccountFromSource( address(_token), _account, address(_source), pulledAmount ); } // ***** Internal Push Receiving Functions ***** /** * @notice Registers a push dispensation */ function registerDispensationPushForAccountInternal( string calldata dispensationKey, uint256 dispensationRoundNumber, address _token, address _account, uint256 _amount, address _pusher ) internal { creditTokenInternal(_token, _account, _amount); emit TokenPushedForAccount( dispensationKey, _token, _account, _pusher, dispensationRoundNumber, _amount ); } // ***** Internal Access Functions ***** function isRegisteredPusher( address _token, address _pusher ) internal view returns (bool) { DispensationPushLevel pusherLevel = dispensationPusherLevels[_token][ _pusher ]; return pusherLevel != DispensationPushLevel.NONE; } // ***** Internal Registry Functions ***** /** * @notice internal hook function to be called whenever a token source/pusher is added * @dev Call this function after adding source/pusher. */ function addTokenToListsIfNeeded(address _token) internal { bool isCurrentlyDispensed = isTokenCurrentlyDispensed[_token]; // If token is not currently dispensed, there is nothing more to do if (isCurrentlyDispensed) { return; } // Add to ever dispensed list if (!wasTokenEverDispensed[_token]) { // Storage allTokensEverDispensed.push(_token); wasTokenEverDispensed[_token] = true; // Event emit TokenAddedToEverDispensed(_token); } // Add to currently dispensed list if (!isCurrentlyDispensed) { // Storage allTokensCurrentlyDispensed.push(_token); isTokenCurrentlyDispensed[_token] = true; // Event emit TokenAddedToCurrentlyDispensed(_token); } } /** * @notice internal hook function to be called whenever a token source/pusher is removed * @dev Call this function after removing source/pusher. */ function removeTokenFromListsIfNeeded(address _token) internal { uint256 pullSourcesCount = pullSourcesForToken[_token].length; uint256 pushersCount = pushersForToken[_token].length; if (pullSourcesCount == 0 && pushersCount == 0) { // Storage // Remove from currently dispensed list for (uint i = 0; i < allTokensCurrentlyDispensed.length; i++) { if (allTokensCurrentlyDispensed[i] == _token) { allTokensCurrentlyDispensed[i] = allTokensCurrentlyDispensed[ allTokensCurrentlyDispensed.length - 1 ]; allTokensCurrentlyDispensed.pop(); break; } } isTokenCurrentlyDispensed[_token] = false; // Event emit TokenRemovedFromCurrentlyDispensed(_token); } } function explainDispensationInternal( string calldata dispensationKey, address _token, string memory name, string memory description ) internal { // Storage dispensationNames[_token][dispensationKey] = name; dispensationDescriptions[_token][dispensationKey] = description; // Event emit DispensationExplained(dispensationKey, _token, name, description); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * 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 Ownable is Context { address private _owner; /** * @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. */ constructor(address initialOwner) { 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) { 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 { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol) pragma solidity ^0.8.20; import {Ownable} from "./Ownable.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 Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { 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 { _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 { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (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 // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; interface IFundingRateModel { // return value is the "funding paid by heavier side" in PRECISION per OI (heavier side) per second // e.g : (0.01 * PRECISION) = Paying (heavier) side (as a whole) pays 1% of funding per second for each OI unit function getFundingRate( uint256 pairId, uint256 openInterestLong, uint256 openInterestShort, uint256 pairMaxOpenInterest ) external view returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; interface IInterestRateModel { // Returns asset/second of interest per borrowed unit // e.g : (0.01 * PRECISION) = 1% of interest per second function getBorrowRate(uint256 utilization) external view returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import "./LexErrors.sol"; import "./LexPoolAdminEnums.sol"; import "./IPoolAccountantV1.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface LexPoolStructs { struct PendingDeposit { uint256 amount; uint256 minAmountOut; } struct PendingRedeem { uint256 amount; uint256 minAmountOut; uint256 maxAmountOut; } } interface LexPoolEvents is LexPoolAdminEnums { event NewEpoch( uint256 epochId, int256 reportedUnrealizedPricePnL, uint256 exchangeRate, uint256 virtualUnderlyingBalance, uint256 totalSupply ); event AddressUpdated(LexPoolAddressesEnum indexed enumCode, address a); event NumberUpdated(LexPoolNumbersEnum indexed enumCode, uint value); event DepositRequest( address indexed user, uint256 amount, uint256 minAmountOut, uint256 processingEpoch ); event RedeemRequest( address indexed user, uint256 amount, uint256 minAmountOut, uint256 processingEpoch ); event ProcessedDeposit( address indexed user, bool deposited, uint256 depositedAmount ); event ProcessedRedeem( address indexed user, bool redeemed, uint256 withdrawnAmount // Underlying amount ); event CanceledDeposit( address indexed user, uint256 epoch, uint256 cancelledAmount ); event CanceledRedeem( address indexed user, uint256 epoch, uint256 cancelledAmount ); event ImmediateDepositAllowedToggled(bool indexed value); event ImmediateDeposit( address indexed depositor, uint256 depositAmount, uint256 mintAmount ); event ReservesWithdrawn( address _to, uint256 interestShare, uint256 totalFundingShare ); } interface ILexPoolFunctionality is IERC20, LexPoolStructs, LexPoolEvents, LexErrors { function setPoolAccountant( IPoolAccountantFunctionality _poolAccountant ) external; function setPnlRole(address pnl) external; function setMaxExtraWithdrawalAmountF(uint256 maxExtra) external; function setEpochsDelayDeposit(uint256 delay) external; function setEpochsDelayRedeem(uint256 delay) external; function setEpochDuration(uint256 duration) external; function setMinDepositAmount(uint256 amount) external; function toggleImmediateDepositAllowed() external; function reduceReserves( address _to ) external returns (uint256 interestShare, uint256 totalFundingShare); function requestDeposit( uint256 amount, uint256 minAmountOut, bytes32 domain, bytes32 referralCode ) external; function requestDepositViaIntent( address user, uint256 amount, uint256 minAmountOut, bytes32 domain, bytes32 referralCode ) external; function requestRedeem(uint256 amount, uint256 minAmountOut) external; function requestRedeemViaIntent( address user, uint256 amount, uint256 minAmountOut ) external; function processDeposit( address[] memory users ) external returns ( uint256 amountDeposited, uint256 amountCancelled, uint256 counterDeposited, uint256 counterCancelled ); function cancelDeposits( address[] memory users, uint256[] memory epochs ) external; function processRedeems( address[] memory users ) external returns ( uint256 amountRedeemed, uint256 amountCancelled, uint256 counterDeposited, uint256 counterCancelled ); function cancelRedeems( address[] memory users, uint256[] memory epochs ) external; function nextEpoch( int256 totalUnrealizedPricePnL ) external returns (uint256 newExchangeRate); function currentVirtualUtilization() external view returns (uint256); function currentVirtualUtilization( uint256 totalBorrows, uint256 totalReserves, int256 unrealizedFunding ) external view returns (uint256); function virtualBalanceForUtilization() external view returns (uint256); function virtualBalanceForUtilization( uint256 extraAmount, int256 unrealizedFunding ) external view returns (uint256); function underlyingBalanceForExchangeRate() external view returns (uint256); function sendAssetToTrader(address to, uint256 amount) external; function isUtilizationForLPsValid() external view returns (bool); } interface ILexPoolV1 is ILexPoolFunctionality { function name() external view returns (string memory); function symbol() external view returns (string memory); function SELF_UNIT_SCALE() external view returns (uint); function underlyingDecimals() external view returns (uint256); function poolAccountant() external view returns (address); function underlying() external view returns (IERC20); function tradingFloor() external view returns (address); function currentEpoch() external view returns (uint256); function currentExchangeRate() external view returns (uint256); function nextEpochStartMin() external view returns (uint256); function epochDuration() external view returns (uint256); function minDepositAmount() external view returns (uint256); function epochsDelayDeposit() external view returns (uint256); function epochsDelayRedeem() external view returns (uint256); function immediateDepositAllowed() external view returns (bool); function pendingDeposits( uint epoch, address account ) external view returns (PendingDeposit memory); function pendingRedeems( uint epoch, address account ) external view returns (PendingRedeem memory); function pendingDepositAmount() external view returns (uint256); function pendingWithdrawalAmount() external view returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; interface ILynxVersionedContract { /** * @notice Returns the name of the contract */ function getContractName() external view returns (string memory); /** * @notice Returns the version of the contract * @dev units are scaled by 1000 (1,000 = 1.00, 1,120 = 1.12) */ function getContractVersion() external view returns (string memory); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import "./LexErrors.sol"; import "./ILexPoolV1.sol"; import "./IInterestRateModel.sol"; import "./IFundingRateModel.sol"; import "./TradingEnumsV1.sol"; interface PoolAccountantStructs { // @note To be used for passing information in function calls struct PositionRegistrationParams { uint256 collateral; uint32 leverage; bool long; uint64 openPrice; uint64 tp; } struct PairFunding { // Slot 0 int256 accPerOiLong; // 32 bytes -- Underlying Decimals // Slot 1 int256 accPerOiShort; // 32 bytes -- Underlying Decimals // Slot 2 uint256 lastUpdateTimestamp; // 32 bytes } struct TradeInitialAccFees { // Slot 0 uint256 borrowIndex; // 32 bytes // Slot 1 int256 funding; // 32 bytes -- underlying units -- Underlying Decimals } struct PairOpenInterest { // Slot 0 uint256 long; // 32 bytes -- underlying units -- Dynamic open interest for long positions // Slot 1 uint256 short; // 32 bytes -- underlying units -- Dynamic open interest for short positions } // This struct is not kept in storage struct PairFromTo { string from; string to; } struct Pair { // Slot 0 uint16 id; // 02 bytes uint16 groupId; // 02 bytes uint16 feeId; // 02 bytes uint32 minLeverage; // 04 bytes uint32 maxLeverage; // 04 bytes uint32 maxBorrowF; // 04 bytes -- FRACTION_SCALE (5) // Slot 1 uint256 maxPositionSize; // 32 bytes -- underlying units // Slot 2 uint256 maxGain; // 32 bytes -- underlying units // Slot 3 uint256 maxOpenInterest; // 32 bytes -- Underlying units // Slot 4 uint256 maxSkew; // 32 bytes -- underlying units // Slot 5 uint256 minOpenFee; // 32 bytes -- underlying units. MAX_UINT means use the default group level value // Slot 6 uint256 minPerformanceFee; // 32 bytes -- underlying units } struct Group { // Slot 0 uint16 id; // 02 bytes uint32 minLeverage; // 04 bytes uint32 maxLeverage; // 04 bytes uint32 maxBorrowF; // 04 bytes -- FRACTION_SCALE (5) // Slot 1 uint256 maxPositionSize; // 32 bytes (Underlying units) // Slot 2 uint256 minOpenFee; // 32 bytes (Underlying uints). MAX_UINT means use the default global level value } struct Fee { // Slot 0 uint16 id; // 02 bytes uint32 openFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of leveraged pos) uint32 closeFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of leveraged pos) uint32 performanceFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of performance) } } interface PoolAccountantEvents is PoolAccountantStructs { event PairAdded( uint256 indexed id, string indexed from, string indexed to, Pair pair ); event PairUpdated(uint256 indexed id, Pair pair); event GroupAdded(uint256 indexed id, string indexed groupName, Group group); event GroupUpdated(uint256 indexed id, Group group); event FeeAdded(uint256 indexed id, string indexed name, Fee fee); event FeeUpdated(uint256 indexed id, Fee fee); event TradeInitialAccFeesStored( bytes32 indexed positionId, uint256 borrowIndex, // uint256 rollover, int256 funding ); event AccrueFunding( uint256 indexed pairId, int256 valueLong, int256 valueShort ); event ProtocolFundingShareAccrued( uint16 indexed pairId, uint256 protocolFundingShare ); // event AccRolloverFeesStored(uint256 pairIndex, uint256 value); event FeesCharged( bytes32 indexed positionId, address indexed trader, uint16 indexed pairId, PositionRegistrationParams positionRegistrationParams, // bool long, // uint256 collateral, // Underlying Decimals // uint256 leverage, int256 profitPrecision, // PRECISION uint256 interest, int256 funding, // Underlying Decimals uint256 closingFee, uint256 tradeValue ); event PerformanceFeeCharging( bytes32 indexed positionId, uint256 performanceFee ); event MaxOpenInterestUpdated(uint256 pairIndex, uint256 maxOpenInterest); event AccrueInterest( uint256 cash, uint256 totalInterestNew, uint256 borrowIndexNew, uint256 interestShareNew ); event Borrow( uint256 indexed pairId, uint256 borrowAmount, uint256 newTotalBorrows ); event Repay( uint256 indexed pairId, uint256 repayAmount, uint256 newTotalBorrows ); } interface IPoolAccountantFunctionality is PoolAccountantStructs, PoolAccountantEvents, LexErrors, TradingEnumsV1 { function setTradeIncentivizer(address _tradeIncentivizer) external; function setMaxGainF(uint256 _maxGainF) external; function setFrm(IFundingRateModel _frm) external; function setMinOpenFee(uint256 min) external; function setLexPartF(uint256 partF) external; function setFundingRateMax(uint256 maxValue) external; function setLiquidationThresholdF(uint256 threshold) external; function setLiquidationFeeF(uint256 fee) external; function setIrm(IInterestRateModel _irm) external; function setIrmHard(IInterestRateModel _irm) external; function setInterestShareFactor(uint256 factor) external; function setFundingShareFactor(uint256 factor) external; function setBorrowRateMax(uint256 rate) external; function setMaxTotalBorrows(uint256 maxBorrows) external; function setMaxVirtualUtilization(uint256 _maxVirtualUtilization) external; function resetTradersPairGains(uint256 pairId) external; function addGroup(Group calldata _group) external; function updateGroup(Group calldata _group) external; function addFee(Fee calldata _fee) external; function updateFee(Fee calldata _fee) external; function addPair(Pair calldata _pair) external; function addPairs(Pair[] calldata _pairs) external; function updatePair(Pair calldata _pair) external; function readAndZeroReserves() external returns (uint256 accumulatedInterestShare, uint256 accFundingShare); function registerOpenTrade( bytes32 positionId, address trader, uint16 pairId, uint256 collateral, uint32 leverage, bool long, uint256 tp, uint256 openPrice ) external returns (uint256 fee, uint256 lexPartFee); function registerCloseTrade( bytes32 positionId, address trader, uint16 pairId, PositionRegistrationParams calldata positionRegistrationParams, uint256 closePrice, PositionCloseType positionCloseType ) external returns ( uint256 closingFee, uint256 tradeValue, int256 profitPrecision, uint finalClosePrice ); function registerUpdateTp( bytes32 positionId, address trader, uint16 pairId, uint256 collateral, uint32 leverage, bool long, uint256 openPrice, uint256 oldTriggerPrice, uint256 triggerPrice ) external; // function registerUpdateSl( // address trader, // uint256 pairIndex, // uint256 index, // uint256 collateral, // uint256 leverage, // bool long, // uint256 openPrice, // uint256 triggerPrice // ) external returns (uint256 fee); function accrueInterest() external returns ( uint256 totalInterestNew, uint256 interestShareNew, uint256 borrowIndexNew ); // Limited only for the LexPool function accrueInterest( uint256 availableCash ) external returns ( uint256 totalInterestNew, uint256 interestShareNew, uint256 borrowIndexNew ); function getTradeClosingValues( bytes32 positionId, uint16 pairId, PositionRegistrationParams calldata positionRegistrationParams, uint256 closePrice, bool isLiquidation ) external returns ( uint256 tradeValue, // Underlying Decimals uint256 safeClosingFee, int256 profitPrecision, uint256 interest, int256 funding ); function getTradeLiquidationPrice( bytes32 positionId, uint16 pairId, uint256 openPrice, // PRICE_SCALE (8) uint256 tp, bool long, uint256 collateral, // Underlying Decimals uint32 leverage ) external returns ( uint256 // PRICE_SCALE (8) ); function calcTradeDynamicFees( bytes32 positionId, uint16 pairId, bool long, uint256 collateral, uint32 leverage, uint256 openPrice, uint256 tp ) external returns (uint256 interest, int256 funding); function unrealizedFunding() external view returns (int256); function totalBorrows() external view returns (uint256); function interestShare() external view returns (uint256); function fundingShare() external view returns (uint256); function totalReservesView() external view returns (uint256); function borrowsAndInterestShare() external view returns (uint256 totalBorrows, uint256 totalInterestShare); function pairTotalOpenInterest( uint256 pairIndex ) external view returns (int256); function pricePnL( uint256 pairId, uint256 price ) external view returns (int256); function getAllSupportedPairIds() external view returns (uint16[] memory); function getAllSupportedGroupsIds() external view returns (uint16[] memory); function getAllSupportedFeeIds() external view returns (uint16[] memory); } interface IPoolAccountantV1 is IPoolAccountantFunctionality { function totalBorrows() external view returns (uint256); function maxTotalBorrows() external view returns (uint256); function pairBorrows(uint256 pairId) external view returns (uint256); function groupBorrows(uint256 groupId) external view returns (uint256); function pairMaxBorrow(uint16 pairId) external view returns (uint256); function groupMaxBorrow(uint16 groupId) external view returns (uint256); function lexPool() external view returns (ILexPoolV1); function maxGainF() external view returns (uint256); function interestShareFactor() external view returns (uint256); function fundingShareFactor() external view returns (uint256); function frm() external view returns (IFundingRateModel); function irm() external view returns (IInterestRateModel); function pairs(uint16 pairId) external view returns (Pair memory); function groups(uint16 groupId) external view returns (Group memory); function fees(uint16 feeId) external view returns (Fee memory); function openInterestInPair( uint pairId ) external view returns (PairOpenInterest memory); function minOpenFee() external view returns (uint256); function liquidationThresholdF() external view returns (uint256); function liquidationFeeF() external view returns (uint256); function lexPartF() external view returns (uint256); function tradersPairGains(uint256 pairId) external view returns (int256); function calcBorrowAmount( uint256 collateral, uint256 leverage, bool long, uint256 openPrice, uint256 tp ) external pure returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; interface LexErrors { enum CapType { NONE, // 0 MIN_OPEN_FEE, // 1 MAX_POS_SIZE_PAIR, // 2 MAX_POS_SIZE_GROUP, // 3 MAX_LEVERAGE, // 4 MIN_LEVERAGE, // 5 MAX_VIRTUAL_UTILIZATION, // 6 MAX_OPEN_INTEREST, // 7 MAX_ABS_SKEW, // 8 MAX_BORROW_PAIR, // 9 MAX_BORROW_GROUP, // 10 MIN_DEPOSIT_AMOUNT, // 11 MAX_ACCUMULATED_GAINS, // 12 BORROW_RATE_MAX, // 13 FUNDING_RATE_MAX, // 14 MAX_POTENTIAL_GAIN, // 15 MAX_TOTAL_BORROW, // 16 MIN_PERFORMANCE_FEE // 17 //... } error CapError(CapType, uint256 value); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.24; interface LexPoolAdminEnums { enum LexPoolAddressesEnum { none, poolAccountant, pnlRole } enum LexPoolNumbersEnum { none, maxExtraWithdrawalAmountF, epochsDelayDeposit, epochsDelayRedeem, epochDuration, minDepositAmount } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; interface TradingEnumsV1 { enum PositionPhase { NONE, OPEN_MARKET, OPEN_LIMIT, OPENED, CLOSE_MARKET, CLOSED } enum OpenOrderType { NONE, MARKET, LIMIT } enum CloseOrderType { NONE, MARKET } enum FeeType { NONE, OPEN_FEE, CLOSE_FEE, TRIGGER_FEE } enum LimitTrigger { NONE, TP, SL, LIQ } enum PositionField { NONE, TP, SL } enum PositionCloseType { NONE, TP, SL, LIQ, MARKET } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import {IDispenserPullSourceV1} from "../interfaces/IDispenserPullSourceV1.sol"; import {TokenHandlingContractUtils} from "../../../Utils/TokenHandlingContractUtils.sol"; abstract contract AbstractPullSourceV1 is TokenHandlingContractUtils, IDispenserPullSourceV1 { // ***** Events ***** event DownstreamDispenserSet( address indexed previousDownstreamDispenser, address indexed newDownstreamDispenser ); event TokenDispensed( address indexed token, address indexed account, address indexed receiver, uint256 amount ); event TokenCredited( address indexed token, address indexed account, uint256 amountCredited ); event TokenDiscredited( address indexed token, address indexed account, uint256 amountCredited ); // ***** Storage ***** address public downstreamDispenser; // @dev : This is the total amount of tokens that are pending to be distributed. // token => total pending distributions mapping(address => uint256) public totalPendingDispensations; // token => account => pending amount mapping(address => mapping(address => uint256)) public pendingDispensationsForAccount; // ***** Modifiers ***** modifier onlyDownstreamDispenser() { require(msg.sender == downstreamDispenser, "NOT_DOWNSTREAM_DISPENSER"); _; } // ***** Views ***** /** * @notice Returns whether the dispenser is matching the source. * @return True if interface matching */ function isDispenserMatchingSourceV1() external pure override returns (bool) { return true; } /** * @notice Returns the pending amount for the account if it were to be pulled now without any state. * @param _token The token to get the pending amount for. * @param _account The account to get the pending amount for. * @return The pending amount for the account. */ function getPendingAmountForAccountView( address _token, address _account ) public view override returns (uint256) { return pendingDispensationsForAccount[_token][_account] + _getExternalPendingAmountForAccountView(_token, _account); } // ***** View-Like ***** /** * @notice Returns the pending amount for the account if it were to be pulled now. * @dev This function is not a view as it may update the state. * @param _token The token to get the pending amount for. * @param _account The account to get the pending amount for. * @return The pending amount for the account. */ function getPendingAmountForAccount( address _token, address _account ) external override returns (uint256) { _pullFromAllSourcesAndRegisterInternal(_token, _account); return pendingDispensationsForAccount[_token][_account]; } // ***** Constructor ***** constructor() {} // ***** Downstream Dispenser Functions ***** /** * @notice Requests to receive the entire amount '_account' is entitled to * @dev This function is expected to be called by the dispenser, the source is expected to transfer tokens to the dispenser * to be credited for '_account' * @param _token The token to request. * @param _account The account to request the token for. */ function pullTokenForAccount( address _token, address _account ) external override onlyDownstreamDispenser { // Sanity require(downstreamDispenser != address(0), "NO_DOWNSTREAM_DISPENSER"); _pullTokenForAccountInternal(_token, _account); } /** * @notice Requests to receive the entire amount '_account' is entitled to * @dev This function is expected to be called by the dispenser, the source is expected to transfer tokens to the dispenser * to be credited for '_account' * @param _token The token to request. * @param _accounts The accounts to request the token for. * @return amounts an array of amounts that were pulled for each account */ function pullTokenForAccounts( address _token, address[] calldata _accounts ) external override onlyDownstreamDispenser returns (uint256[] memory amounts) { // Sanity require(downstreamDispenser != address(0), "NO_DOWNSTREAM_DISPENSER"); amounts = new uint256[](_accounts.length); for (uint256 i = 0; i < _accounts.length; i++) { amounts[i] = _pullTokenForAccountInternal(_token, _accounts[i]); } } // ***** Internal Admin Functions ***** function setDownstreamDispenserInternal( address _downstreamDispenser ) internal { // Storage address previousDownstreamDispenser = downstreamDispenser; downstreamDispenser = _downstreamDispenser; // Event emit DownstreamDispenserSet( previousDownstreamDispenser, _downstreamDispenser ); } // ***** Internal Pulling Functions ***** /** * @notice Implements the behaviour expected from this contract as a 'DispensesPullSource' * @dev will pull from all sources and send and entitlement to 'downstreamDispenser' */ function _pullTokenForAccountInternal( address _token, address _account ) internal returns (uint256 amountDispensedToAccount) { // First pull from all sources available to this contract _pullFromAllSourcesAndRegisterInternal(_token, _account); // Then, dispense to 'downstreamDispenser' amountDispensedToAccount = dispensePendingTokenToReceiverInternal( address(_token), _account, downstreamDispenser ); } /** * @notice Will send all of _account pending _token to _receiver */ function dispensePendingTokenToReceiverInternal( address _token, address _account, address _receiver ) internal returns (uint256 amountDispensed) { // Sanity require(_receiver != address(0), "CANNOT_DISPENSE_TO_ZERO"); // Zero pending amount amountDispensed = pendingDispensationsForAccount[_token][_account]; pendingDispensationsForAccount[_token][_account] = 0; totalPendingDispensations[_token] -= amountDispensed; // Internal hook onTokenDispensedToReceiverInternal( _token, _account, _receiver, amountDispensed ); // Send token sendTokens(_token, _receiver, amountDispensed); // Event emit TokenDispensed(_token, _account, _receiver, amountDispensed); } // ***** Internal Credit/Discredit Functions ***** /** * @notice Increases pending amount for account */ function creditTokenInternal( address _token, address _account, uint256 _amount ) internal { uint256 newAccountPending = pendingDispensationsForAccount[_token][ _account ] + _amount; uint256 newTokenPending = totalPendingDispensations[_token] + _amount; pendingDispensationsForAccount[_token][_account] = newAccountPending; totalPendingDispensations[_token] = newTokenPending; emit TokenCredited(_token, _account, _amount); } /** * @notice Reduces pending amount for account * @dev 0 means all. Will revert if amount is greater than pending amount */ function discreditTokenInternal( address _token, address _account, uint256 _amount, address _destination ) internal { // Start by pulling from all sources _pullFromAllSourcesAndRegisterInternal(_token, _account); uint256 currentPending = pendingDispensationsForAccount[_token][_account]; uint256 amountReduced = 0; if (_amount == 0) { pendingDispensationsForAccount[_token][_account] = 0; amountReduced = currentPending; } else { require(currentPending >= _amount, "AMOUNT_EXCEEDS_PENDING"); pendingDispensationsForAccount[_token][_account] = currentPending - _amount; amountReduced = _amount; } // Update total pending and avoid underflow uint256 currentTotalPending = totalPendingDispensations[_token]; totalPendingDispensations[_token] = amountReduced > currentTotalPending ? 0 : currentTotalPending - amountReduced; sendTokens(_token, _destination, amountReduced); emit TokenDiscredited(_token, _account, amountReduced); } // ***** Internal Overridable Functions ***** /** * @notice Pulls the pending amount for the account from the external sources. * @dev This function is virtual and can be overridden and implemented by the child contract. * @param _token The token to pull the pending amount for. * @param _account The account to pull the pending amount for. * @return externalPulledAmount The amount pulled. */ function _pullFromAllSourcesAndRegisterInternal( address _token, address _account ) internal virtual returns (uint256 externalPulledAmount) {} /** * @notice Reads the pending amount for the account from the external sources. * @dev This function is virtual and can be overridden and implemented by the child contract. * @param _token The token to pull the pending amount for. * @param _account The account to pull the pending amount for. * @return externalPendingAmount The amount read. */ function _getExternalPendingAmountForAccountView( address _token, address _account ) internal view virtual returns (uint256 externalPendingAmount) {} /** * @notice Called upon token dispensation to allow custom logic. * @dev This function is virtual used as a hook for inheriting contracts * @param _token The token to send. * @param _receiver The receiver to send the tokens to. * @param amountDispensed The amount to be send. */ function onTokenDispensedToReceiverInternal( address _token, address _account, address _receiver, uint256 amountDispensed ) internal virtual {} }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; interface IDispenserPullSourceV1 { /** * @notice Returns whether the dispenser is matching the source. * @return True if interface matching */ function isDispenserMatchingSourceV1() external pure returns (bool); /** * @notice Returns the pending amount for the account if it were to be pulled now. * @dev This function is not a view as it may update the state. * @param _token The token to get the pending amount for. * @param _account The account to get the pending amount for. * @return The pending amount for the account. */ function getPendingAmountForAccount( address _token, address _account ) external returns (uint256); /** * @notice Returns the pending amount for the account if it were to be pulled now without any state. * @param _token The token to get the pending amount for. * @param _account The account to get the pending amount for. * @return The pending amount for the account. */ function getPendingAmountForAccountView( address _token, address _account ) external view returns (uint256); /** * @notice Requests to receive the entire amount '_account' is entitled to * @dev This function is expected to be called by the dispenser, the source is expected to transfer tokens to the dispenser * to be credited for '_account' * @param _token The token to request. * @param _account The account to request the token for. */ function pullTokenForAccount(address _token, address _account) external; /** * @notice Requests to receive the entire amount '_account' is entitled to * @dev This function is expected to be called by the dispenser, the source is expected to transfer tokens to the dispenser * to be credited for '_account' * @param _token The token to request. * @param _accounts The accounts to request the token for. * @return amounts an array of amounts that were pulled for each account */ function pullTokenForAccounts( address _token, address[] calldata _accounts ) external returns (uint256[] memory amounts); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; interface IPushableDispenserV1 { /** * @notice Flag for interface identification * @return True if interface matching */ function isPushableDispenserV1() external pure returns (bool); /** * @notice Called by the Pusher, dispense should pull _amount from Pusher. * @dev The dispenser is expected to credit the account with the tokens pulled from sender * @param dispensationKey The dispensation key. * @param dispensationRoundNumber The dispensation round number, if valid. * @param _token The token to push. * @param _account The account to push the token for. * @param _amount The amount to push. */ function receiveDispensationPushForAccount( string calldata dispensationKey, uint256 dispensationRoundNumber, address _token, address _account, uint256 _amount ) external; /** * @notice Called by the Pusher, dispense should pull SUM(_amounts) from Pusher. * @dev The dispenser is expected to credit the accounts with the tokens pulled from sender * @param dispensationKey The dispensation key. * @param dispensationRoundNumber The dispensation round number, if valid. * @param _token The token to push. * @param _accounts The accounts to push the token for. * @param _amounts The amounts to push per account. */ function receiveDispensationPushForAccounts( string calldata dispensationKey, uint256 dispensationRoundNumber, address _token, address[] calldata _accounts, uint256[] calldata _amounts ) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; /** * @title TokenHandlingContractUtils * @notice Used to handle token related operations. * @dev DO NOT ADD STORAGE TO THIS CONTRACT */ contract TokenHandlingContractUtils { using SafeERC20 for IERC20; // ***** Events ***** event TokensSwept( address indexed token, address indexed receiver, uint256 amount ); // ***** Internal Util Functions ***** /** * @notice Sweep any tokens from the contract * @param _token The token to sweep * @param _amount The amount to sweep */ function sweepTokensInternal( address _token, address _receiver, uint256 _amount ) internal { uint256 amount = _amount > 0 ? _amount : getSelfBalanceInTokenInternal(_token); sendTokens(_token, _receiver, amount); emit TokensSwept(address(_token), _receiver, amount); } /** * Utility function to safely take tokens (ERC20) from a pre-approved account * @dev Will revert if the contract will not get the exact 'amount' value */ function takeTokens(address _token, address _from, uint256 _amount) internal { uint256 balanceBefore = getSelfBalanceInTokenInternal(_token); IERC20(_token).safeTransferFrom(_from, address(this), _amount); uint256 balanceAfter = getSelfBalanceInTokenInternal(_token); require(balanceAfter - balanceBefore == _amount, "DID_NOT_RECEIVE_EXACT"); } /** * Utility function to safely send tokens (ERC20) */ function sendTokens(address _token, address _to, uint256 _amount) internal { IERC20(_token).safeTransfer(_to, _amount); } function getSelfBalanceInTokenInternal( address _token ) internal view returns (uint256) { return IERC20(_token).balanceOf(address(this)); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"dispensationKey","type":"string"},{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"DispensationEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"dispensationKey","type":"string"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"DispensationExplained","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"dispensationKey","type":"string"},{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"DispensationStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousDownstreamDispenser","type":"address"},{"indexed":true,"internalType":"address","name":"newDownstreamDispenser","type":"address"}],"name":"DownstreamDispenserSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"value","type":"bool"}],"name":"IsAllClaimingPausedFlagSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"bool","name":"value","type":"bool"}],"name":"IsClaimingPausedForTokenFlagSet","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":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"pullSource","type":"address"}],"name":"PullSourceAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"pullSource","type":"address"}],"name":"PullSourceRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"address","name":"_pusher","type":"address"},{"indexed":false,"internalType":"enum GeneralTokenDispenserV1.DispensationPushLevel","name":"level","type":"uint8"}],"name":"PusherRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":true,"internalType":"address","name":"_pusher","type":"address"}],"name":"PusherUnregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"TokenAddedToCurrentlyDispensed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"TokenAddedToEverDispensed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountCredited","type":"uint256"}],"name":"TokenCredited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountCredited","type":"uint256"}],"name":"TokenDiscredited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenDispensed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"source","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenPulledForAccountFromSource","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"dispensationKey","type":"string"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"pusher","type":"address"},{"indexed":false,"internalType":"uint256","name":"round","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenPushedForAccount","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"TokenRemovedFromCurrentlyDispensed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensSwept","type":"event"},{"inputs":[],"name":"CONTRACT_NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONTRACT_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_pullSource","type":"address"}],"name":"addPullSource","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"allOngoingDispensationsForToken","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allTokensCurrentlyDispensed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allTokensEverDispensed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_account","type":"address"}],"name":"claimTokenFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_destination","type":"address"}],"name":"discreditAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address[]","name":"_accounts","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address","name":"_destination","type":"address"}],"name":"discreditAccounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"string","name":"","type":"string"}],"name":"dispensationDescriptions","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"string","name":"","type":"string"}],"name":"dispensationNames","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"dispensationPusherLevels","outputs":[{"internalType":"enum GeneralTokenDispenserV1.DispensationPushLevel","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"downstreamDispensationsForAccount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"downstreamDispenser","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_dispensationKey","type":"string"},{"internalType":"address","name":"_token","type":"address"}],"name":"endDispensation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_dispensationKey","type":"string"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_description","type":"string"}],"name":"explainDispensation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getAllOngoingDispensationsForToken","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllTokensCurrentlyDispensed","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllTokensEverDispensed","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getContractVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"string","name":"dispensationKey","type":"string"},{"internalType":"address","name":"_token","type":"address"}],"name":"getDispensationInfo","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"description","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_pusher","type":"address"}],"name":"getDispensationPusherLevel","outputs":[{"internalType":"enum GeneralTokenDispenserV1.DispensationPushLevel","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_account","type":"address"}],"name":"getPendingAmountForAccount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_account","type":"address"}],"name":"getPendingAmountForAccountView","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getPullSourcesForToken","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getPushersForToken","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"historicDispensationsForAccount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isAllClaimingPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isClaimingPausedForToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isDispenserMatchingSourceV1","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"string","name":"","type":"string"}],"name":"isOngoingDispensation","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isPullSourceForToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPushableDispenserV1","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isTokenCurrentlyDispensed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"pendingDispensationsForAccount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_account","type":"address"}],"name":"pullAllAndClaimFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_account","type":"address"},{"internalType":"address[]","name":"pullSources","type":"address[]"}],"name":"pullSomeAndClaimFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"pullSourcesForToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_account","type":"address"}],"name":"pullTokenForAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address[]","name":"_accounts","type":"address[]"}],"name":"pullTokenForAccounts","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"pushersForToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_dispensationKey","type":"string"},{"internalType":"uint256","name":"_dispensationRoundNumber","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"receiveDispensationPushForAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_dispensationKey","type":"string"},{"internalType":"uint256","name":"_dispensationRoundNumber","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"address[]","name":"_accounts","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"receiveDispensationPushForAccounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_pusher","type":"address"},{"internalType":"enum GeneralTokenDispenserV1.DispensationPushLevel","name":"level","type":"uint8"}],"name":"registerPusher","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_pullSource","type":"address"}],"name":"removePullSource","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_downstreamDispenser","type":"address"}],"name":"setDownstreamDispenser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_value","type":"bool"}],"name":"setIsAllClaimingPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"bool","name":"_value","type":"bool"}],"name":"setIsClaimingPausedForToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_dispensationKey","type":"string"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_description","type":"string"}],"name":"startDispensation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"sweepTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalPendingDispensations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_pusher","type":"address"}],"name":"unregisterPusher","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wasTokenEverDispensed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5033806200003957604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b62000044816200004b565b50620000b9565b600180546001600160a01b0319169055620000668162000069565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6143a080620000c96000396000f3fe608060405234801561001057600080fd5b50600436106103975760003560e01c806379ba5097116101e9578063b7b6287e1161010f578063e30c3978116100ad578063f3695d981161007c578063f3695d98146108c8578063f44978f914610949578063f5f5ba721461095c578063ffb85f5a1461098f57600080fd5b8063e30c3978146108e2578063e50c26b9146108f3578063e9597a8b14610916578063f2fde38b1461093657600080fd5b8063b987b2e8116100e9578063b987b2e814610887578063cc236cc7146108b5578063d1a8ff54146108c8578063dec66036146108cf57600080fd5b8063b7b6287e14610859578063b836441e1461086c578063b8b65cf41461087457600080fd5b80638da5cb5b116101875780639d8ec144116101565780639d8ec144146107e8578063a8bc01a4146107fb578063a9b8c5b41461081b578063b058fa361461084657600080fd5b80638da5cb5b146107a45780638e681ec3146107b55780638e96317f146107c85780639553c578146107db57600080fd5b806386725a75116101c357806386725a7514610720578063874951c3146107335780638aa10435146107725780638bf4d4af1461079157600080fd5b806379ba5097146106f257806379c12917146106fa57806385f9db671461070d57600080fd5b8063330ca298116102ce5780635b2e448f1161026c5780636a274d221161023b5780636a274d221461068c578063715018a6146106b757806374b3ff4f146106bf5780637820c216146106df57600080fd5b80635b2e448f14610602578063614d08f814610615578063647aefbd1461064b578063677625a71461067957600080fd5b806342456d0d116102a857806342456d0d146105805780634b98684f146105935780634eb4164c146105a657806352fc7984146105b957600080fd5b8063330ca2981461051d57806336fa5f081461053e57806338b903331461055157600080fd5b80631a6748f41161033b57806323e86e341161031557806323e86e34146104c1578063247858ba146104d45780632d7ce37f146104e75780632eb37ff4146104fa57600080fd5b80631a6748f414610470578063213e832814610483578063231d89c8146104ae57600080fd5b80630dd7b0cb116103775780630dd7b0cb146104225780630e6adf37146104355780630eceebc51461044a57806311bb93511461045d57600080fd5b80626dff4b1461039c57806272333d146103d4578063099b58fd146103e9575b600080fd5b6103bf6103aa36600461366f565b600d6020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6103e76103e236600461368a565b6109a2565b005b6104146103f736600461368a565b600f60209081526000928352604080842090915290825290205481565b6040519081526020016103cb565b6103e761043036600461368a565b610a5d565b61043d610ac5565b6040516103cb91906136bd565b6103e7610458366004613755565b610b27565b61043d61046b36600461366f565b610be5565b6103e761047e36600461368a565b610c5b565b6104966104913660046137b5565b610e10565b6040516001600160a01b0390911681526020016103cb565b61043d6104bc36600461366f565b610e3a565b6103e76104cf36600461380f565b610eae565b600254610496906001600160a01b031681565b6104146104f536600461368a565b610f35565b6103bf61050836600461366f565b60066020526000908152604090205460ff1681565b61053061052b3660046138bc565b610f70565b6040516103cb92919061395f565b61049661054c36600461398d565b611113565b6105736040518060400160405280600381526020016203130360ec1b81525081565b6040516103cb91906139b7565b6103e761058e36600461368a565b61114b565b6103e76105a13660046139ca565b6111be565b6103e76105b4366004613a15565b61135b565b6105f56105c736600461368a565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b6040516103cb9190613a78565b6103e761061036600461368a565b611375565b6105736040518060400160405280601781526020017647656e6572616c546f6b656e44697370656e736572563160481b81525081565b6103bf61065936600461368a565b600860209081526000928352604080842090915290825290205460ff1681565b6103e7610687366004613aae565b611559565b61041461069a36600461368a565b601060209081526000928352604080842090915290825290205481565b6103e76115ee565b6106d26106cd366004613acb565b611602565b6040516103cb9190613b1d565b6104966106ed36600461398d565b611758565b6103e7611774565b61041461070836600461368a565b6117b8565b6103e761071b366004613b55565b6117fb565b6103e761072e36600461366f565b6118a1565b6103bf610741366004613bfa565b6012602090815260009283526040909220815180830184018051928152908401929093019190912091525460ff1681565b60408051808201909152600381526203130360ec1b6020820152610573565b61057361079f366004613bfa565b6118b2565b6000546001600160a01b0316610496565b6103e76107c336600461380f565b611968565b6103e76107d63660046138bc565b611b32565b6005546103bf9060ff1681565b6105736107f636600461398d565b611d77565b61080e61080936600461366f565b611daf565b6040516103cb9190613cbb565b61041461082936600461368a565b600460209081526000928352604080842090915290825290205481565b6103e7610854366004613d1f565b611e9e565b6104966108673660046137b5565b611f75565b61043d611f85565b610573610882366004613bfa565b611fe5565b6105f561089536600461368a565b600a60209081526000928352604080842090915290825290205460ff1681565b6103e76108c3366004613d94565b61201a565b60016103bf565b6103e76108dd36600461398d565b6121cb565b6001546001600160a01b0316610496565b6103bf61090136600461366f565b600e6020526000908152604090205460ff1681565b61041461092436600461366f565b60036020526000908152604090205481565b6103e761094436600461366f565b6121f3565b6103e7610957366004613e4a565b612264565b60408051808201909152601781527647656e6572616c546f6b656e44697370656e736572563160481b6020820152610573565b6103e761099d36600461368a565b612324565b6002546001600160a01b031633146109fc5760405162461bcd60e51b81526020600482015260186024820152772727aa2fa227aba729aa2922a0a6afa224a9a822a729a2a960411b60448201526064015b60405180910390fd5b6002546001600160a01b0316610a4e5760405162461bcd60e51b81526020600482015260176024820152762727afa227aba729aa2922a0a6afa224a9a822a729a2a960491b60448201526064016109f3565b610a588282612526565b505050565b600554829060ff1615610a825760405162461bcd60e51b81526004016109f390613e81565b6001600160a01b03811660009081526006602052604090205460ff1615610abb5760405162461bcd60e51b81526004016109f390613eae565b610a58838361254c565b6060600c805480602002602001604051908101604052809291908181526020018280548015610b1d57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610aff575b5050505050905090565b600554849060ff1615610b4c5760405162461bcd60e51b81526004016109f390613e81565b6001600160a01b03811660009081526006602052604090205460ff1615610b855760405162461bcd60e51b81526004016109f390613eae565b81610bc85760405162461bcd60e51b81526020600482015260136024820152721393d7d4d3d55490d154d7d41493d592511151606a1b60448201526064016109f3565b610bd483838787612557565b610bde858561254c565b5050505050565b6001600160a01b038116600090815260096020908152604091829020805483518184028101840190945280845260609392830182828015610c4f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c31575b50505050509050919050565b610c6361259c565b610c6d82826125c9565b610c895760405162461bcd60e51b81526004016109f390613ee5565b6001600160a01b038281166000818152600a602090815260408083209486168352938152838220805460ff191690559181526009909152908120905b8154811015610dc157826001600160a01b0316828281548110610cea57610cea613f14565b6000918252602090912001546001600160a01b031603610db95781548290610d1490600190613f40565b81548110610d2457610d24613f14565b9060005260206000200160009054906101000a90046001600160a01b0316828281548110610d5457610d54613f14565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081805480610d9257610d92613f53565b600082815260209020810160001990810180546001600160a01b0319169055019055610dc1565b600101610cc5565b50610dcb83612611565b816001600160a01b0316836001600160a01b03167f5144cb6540b0046ea54d1878787028f5635d75813e2aaf25ea0904fc69f47e3360405160405180910390a3505050565b600b8181548110610e2057600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b038116600090815260076020908152604091829020805483518184028101840190945280845260609392830182828015610c4f576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610c315750505050509050919050565b610eb661259c565b610f2c87878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8b01819004810282018101909252898152925089915088908190840183828082843760009201919091525061279192505050565b50505050505050565b6000610f418383612881565b50506001600160a01b038083166000908152600460209081526040808320938516835292905220545b92915050565b6001600160a01b0381166000908152601360205260409081902090516060918291610f9e9087908790613f69565b908152602001604051809103902060146000856001600160a01b03166001600160a01b031681526020019081526020016000208686604051610fe1929190613f69565b9081526020016040518091039020818054610ffb90613f79565b80601f016020809104026020016040519081016040528092919081815260200182805461102790613f79565b80156110745780601f1061104957610100808354040283529160200191611074565b820191906000526020600020905b81548152906001019060200180831161105757829003601f168201915b5050505050915080805461108790613f79565b80601f01602080910402602001604051908101604052809291908181526020018280546110b390613f79565b80156111005780601f106110d557610100808354040283529160200191611100565b820191906000526020600020905b8154815290600101906020018083116110e357829003601f168201915b5050505050905091509150935093915050565b6007602052816000526040600020818154811061112f57600080fd5b6000918252602090912001546001600160a01b03169150829050565b600554829060ff16156111705760405162461bcd60e51b81526004016109f390613e81565b6001600160a01b03811660009081526006602052604090205460ff16156111a95760405162461bcd60e51b81526004016109f390613eae565b6111b38383612881565b50610a58838361254c565b6111c661259c565b6111d083836125c9565b1561121d5760405162461bcd60e51b815260206004820152601960248201527f5055534845525f414c52454144595f524547495354455245440000000000000060448201526064016109f3565b600081600181111561123157611231613a62565b0361127e5760405162461bcd60e51b815260206004820152601a60248201527f43414e4e4f545f52454749535445525f4e4f4e455f4c4556454c00000000000060448201526064016109f3565b6001600160a01b038084166000908152600a60209081526040808320938616835292905220805482919060ff1916600183818111156112bf576112bf613a62565b02179055506001600160a01b0383811660009081526009602090815260408220805460018101825590835291200180546001600160a01b03191691841691909117905561130b8361293f565b816001600160a01b0316836001600160a01b03167f196fa3ab7946db556eb94c3423dc51d780f3a397bcaecd284b44456dc88324d98360405161134e9190613a78565b60405180910390a3505050565b61136361259c565b61136f84848484612aa7565b50505050565b61137d61259c565b6001600160a01b0382166000908152600760205260408120815b815481101561149757836001600160a01b03168282815481106113bc576113bc613f14565b6000918252602090912001546001600160a01b03160361148f57815482906113e690600190613f40565b815481106113f6576113f6613f14565b9060005260206000200160009054906101000a90046001600160a01b031682828154811061142657611426613f14565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508180548061146457611464613f53565b600082815260209020810160001990810180546001600160a01b031916905501905560019250611497565b600101611397565b50816114dd5760405162461bcd60e51b81526020600482015260156024820152741415531317d4d3d55490d157d393d517d193d55391605a1b60448201526064016109f3565b6001600160a01b038085166000908152600860209081526040808320938716835292905220805460ff1916905561151384612611565b826001600160a01b0316846001600160a01b03167f493b1bf532df7004894c240578a101f10cbb9216cc9b787dbe3cd9a81b52c4e460405160405180910390a350505050565b61156161259c565b60055481151560ff9091161515036115a95760405162461bcd60e51b815260206004820152600b60248201526a1053149150511657d4d15560aa1b60448201526064016109f3565b6005805460ff191682151590811790915560405160ff9091161515907fa042e27caefe535b8657a25f0d53a680853b51681d7d510291f72ab708b72bf090600090a250565b6115f661259c565b6116006000612c39565b565b6002546060906001600160a01b0316331461165a5760405162461bcd60e51b81526020600482015260186024820152772727aa2fa227aba729aa2922a0a6afa224a9a822a729a2a960411b60448201526064016109f3565b6002546001600160a01b03166116ac5760405162461bcd60e51b81526020600482015260176024820152762727afa227aba729aa2922a0a6afa224a9a822a729a2a960491b60448201526064016109f3565b816001600160401b038111156116c4576116c4613be4565b6040519080825280602002602001820160405280156116ed578160200160208202803683370190505b50905060005b828110156117505761172b8585858481811061171157611711613f14565b9050602002016020810190611726919061366f565b612526565b82828151811061173d5761173d613f14565b60209081029190910101526001016116f3565b509392505050565b6009602052816000526040600020818154811061112f57600080fd5b60015433906001600160a01b031681146117ac5760405163118cdaa760e01b81526001600160a01b03821660048201526024016109f3565b6117b581612c39565b50565b60006117c48383612c52565b6001600160a01b038085166000908152600460209081526040808320938716835292905220546117f49190613fb3565b9392505050565b61180361259c565b8382146118445760405162461bcd60e51b815260206004820152600f60248201526e0988a9c8ea890be9a92a69a82a8869608b1b60448201526064016109f3565b60005b84811015610f2c576118998787878481811061186557611865613f14565b905060200201602081019061187a919061366f565b86868581811061188c5761188c613f14565b9050602002013585612aa7565b600101611847565b6118a961259c565b6117b581612d74565b60146020908152600092835260409092208151808301840180519281529084019290930191909120915280546118e790613f79565b80601f016020809104026020016040519081016040528092919081815260200182805461191390613f79565b80156119605780601f1061193557610100808354040283529160200191611960565b820191906000526020600020905b81548152906001019060200180831161194357829003601f168201915b505050505081565b61197061259c565b6001600160a01b0385166000908152601260205260409081902090516119999089908990613f69565b9081526040519081900360200190205460ff16156119eb5760405162461bcd60e51b815260206004820152600f60248201526e414c52454144595f4f4e474f494e4760881b60448201526064016109f3565b6001600160a01b03851660009081526012602052604090819020905160019190611a18908a908a90613f69565b9081526040805160209281900383019020805460ff1916931515939093179092556001600160a01b0387166000908152601182529182208054600181018255908352912001611a6887898361402b565b50611adf87878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8b01819004810282018101909252898152925089915088908190840183828082843760009201919091525061279192505050565b846001600160a01b03168787604051611af9929190613f69565b604051908190038120907f2a9b4fc367f7e38f84011e08df7345c49bc5ab25bf5a6fa7a1c7c02f592ba8e490600090a350505050505050565b611b3a61259c565b6001600160a01b038116600090815260126020526040908190209051611b639085908590613f69565b9081526040519081900360200190205460ff16611b925760405162461bcd60e51b81526004016109f3906140e4565b6001600160a01b0381166000908152601260205260408082209051611bba9086908690613f69565b9081526040805160209281900383019020805460ff1916931515939093179092556001600160a01b03831660009081526011909152908120905b8154811015611cfb578484604051602001611c10929190613f69565b60405160208183030381529060405280519060200120828281548110611c3857611c38613f14565b90600052602060002001604051602001611c52919061411b565b6040516020818303038152906040528051906020012003611cf35781548290611c7d90600190613f40565b81548110611c8d57611c8d613f14565b90600052602060002001828281548110611ca957611ca9613f14565b906000526020600020019081611cbf9190614191565b5081805480611cd057611cd0613f53565b600190038181906000526020600020016000611cec9190613605565b9055611cfb565b600101611bf4565b50611d278484846040518060200160405280600081525060405180602001604052806000815250612791565b816001600160a01b03168484604051611d41929190613f69565b604051908190038120907fab45c658146b5490390503d9570ee0393d223a399a8b147e4a31f164e6b3dab890600090a350505050565b60116020528160005260406000208181548110611d9357600080fd5b906000526020600020016000915091505080546118e790613f79565b6001600160a01b0381166000908152601160209081526040808320805482518185028101850190935280835260609492939192909184015b82821015611e93578382906000526020600020018054611e0690613f79565b80601f0160208091040260200160405190810160405280929190818152602001828054611e3290613f79565b8015611e7f5780601f10611e5457610100808354040283529160200191611e7f565b820191906000526020600020905b815481529060010190602001808311611e6257829003601f168201915b505050505081526020019060010190611de7565b505050509050919050565b33611ea984826125c9565b611ec55760405162461bcd60e51b81526004016109f390613ee5565b6001600160a01b038416600090815260126020526040908190209051611eee9089908990613f69565b9081526040519081900360200190205460ff16611f1d5760405162461bcd60e51b81526004016109f3906140e4565b60008211611f5b5760405162461bcd60e51b815260206004820152600b60248201526a414d4f554e545f5a45524f60a81b60448201526064016109f3565b611f66843384612dc6565b610f2c87878787878787612e45565b600c8181548110610e2057600080fd5b6060600b805480602002602001604051908101604052809291908181526020018280548015610b1d576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610aff575050505050905090565b60136020908152600092835260409092208151808301840180519281529084019290930191909120915280546118e790613f79565b82811461205b5760405162461bcd60e51b815260206004820152600f60248201526e0988a9c8ea890be9a92a69a82a8869608b1b60448201526064016109f3565b3361206686826125c9565b6120825760405162461bcd60e51b81526004016109f390613ee5565b6001600160a01b0386166000908152601260205260409081902090516120ab908b908b90613f69565b9081526040519081900360200190205460ff166120da5760405162461bcd60e51b81526004016109f3906140e4565b6000805b85811015612114578484828181106120f8576120f8613f14565b905060200201358261210a9190613fb3565b91506001016120de565b50600081116121535760405162461bcd60e51b815260206004820152600b60248201526a414d4f554e545f5a45524f60a81b60448201526064016109f3565b61215e878383612dc6565b60005b858110156121be576121b68b8b8b8b8b8b8781811061218257612182613f14565b9050602002016020810190612197919061366f565b8a8a888181106121a9576121a9613f14565b9050602002013589612e45565b600101612161565b5050505050505050505050565b6121d361259c565b6121ef826121e96000546001600160a01b031690565b83612ece565b5050565b6121fb61259c565b600180546001600160a01b0383166001600160a01b0319909116811790915561222c6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b61226c61259c565b6001600160a01b03821660009081526006602052604090205481151560ff9091161515036122ca5760405162461bcd60e51b815260206004820152600b60248201526a1053149150511657d4d15560aa1b60448201526064016109f3565b6001600160a01b038216600081815260066020526040808220805460ff1916851515908117909155905160ff909116151592917fe766dd0694ff9295340d29c34dbc30b4f70c083307c3c81e5285dba3c073274991a35050565b61232c61259c565b806001600160a01b031663f3695d986040518163ffffffff1660e01b8152600401602060405180830381865afa15801561236a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238e9190614267565b6123cf5760405162461bcd60e51b81526020600482015260126024820152714e4f545f50554c4c5f534f555243455f563160701b60448201526064016109f3565b6001600160a01b0382166000908152600760205260408120905b815481101561247857826001600160a01b031682828154811061240e5761240e613f14565b6000918252602090912001546001600160a01b0316036124705760405162461bcd60e51b815260206004820152601960248201527f50554c4c5f534f555243455f414c52454144595f41444445440000000000000060448201526064016109f3565b6001016123e9565b506001600160a01b0383811660008181526007602090815260408083208054600180820183559185528385200180546001600160a01b03191696891696871790559383526008825280832094835293905291909120805460ff191690911790556124e18361293f565b816001600160a01b0316836001600160a01b03167f46f9eb8ce96dd38714a7b9ac42bdc69a3313c60e548cf5ef032570b793045fdd60405160405180910390a3505050565b60006125328383612881565b506002546117f490849084906001600160a01b0316612f47565b610a58828283612f47565b60005b83811015610bde5761259385858381811061257757612577613f14565b905060200201602081019061258c919061366f565b8484613063565b5060010161255a565b6000546001600160a01b031633146116005760405163118cdaa760e01b81523360048201526024016109f3565b6001600160a01b038083166000908152600a6020908152604080832093851683529290529081205460ff168181600181111561260757612607613a62565b1415949350505050565b6001600160a01b03811660009081526007602090815260408083205460099092529091205481158015612642575080155b15610a585760005b600b5481101561274557836001600160a01b0316600b828154811061267157612671613f14565b6000918252602090912001546001600160a01b03160361273d57600b805461269b90600190613f40565b815481106126ab576126ab613f14565b600091825260209091200154600b80546001600160a01b0390921691839081106126d7576126d7613f14565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600b80548061271657612716613f53565b600082815260209020810160001990810180546001600160a01b0319169055019055612745565b60010161264a565b506001600160a01b0383166000818152600e6020526040808220805460ff19169055517f5458626fa48fdcbb7a33a1f144e182222b16ecfdd862b844752fc0061c55b45a9190a2505050565b6001600160a01b0383166000908152601360205260409081902090518391906127bd9088908890613f69565b908152602001604051809103902090816127d79190614284565b506001600160a01b0383166000908152601460205260409081902090518291906128049088908890613f69565b9081526020016040518091039020908161281e9190614284565b50826001600160a01b03168585604051612839929190613f69565b60405180910390207f6580caef4438dbfe0b139727fbf172f51a284bf6e86fca731f02eea21ca58097848460405161287292919061395f565b60405180910390a35050505050565b6001600160a01b0382166000908152600760209081526040808320805482518185028101850190935280835284938301828280156128e857602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116128ca575b505050505090506000915060005b81518110156129375761292382828151811061291457612914613f14565b60200260200101518686613063565b61292d9084613fb3565b92506001016128f6565b505092915050565b6001600160a01b0381166000908152600e602052604090205460ff168015612965575050565b6001600160a01b0382166000908152600d602052604090205460ff16612a1257600c805460018082019092557fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b0319166001600160a01b0385169081179091556000818152600d6020526040808220805460ff1916909417909355915190917ffef74848d3638a6ed3547447282ce33584cf17be953e3f9f7c6824e2284969e991a25b806121ef57600b805460018082019092557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b0319166001600160a01b0385169081179091556000818152600e6020526040808220805460ff1916909417909355915190917f74e2d6b252841daa9d389cafd5dca3a3927ef59ebfa28699c1748c1a1603250e91a25050565b612ab18484612881565b506001600160a01b03808516600090815260046020908152604080832093871683529290529081205490838103612b1157506001600160a01b03808616600090815260046020908152604080832093881683529290529081205580612b8d565b83821015612b5a5760405162461bcd60e51b8152602060048201526016602482015275414d4f554e545f455843454544535f50454e44494e4760501b60448201526064016109f3565b612b648483613f40565b6001600160a01b038088166000908152600460209081526040808320938a168352929052205550825b6001600160a01b038616600090815260036020526040902054808211612bbc57612bb78282613f40565b612bbf565b60005b6001600160a01b038816600090815260036020526040902055612be387858461307d565b856001600160a01b0316876001600160a01b03167f13268b3f271140c93c5d8b166950c19ad5320c82e78b1aa918bfb842ff13454584604051612c2891815260200190565b60405180910390a350505050505050565b600180546001600160a01b03191690556117b581613091565b6001600160a01b038216600090815260076020908152604080832080548251818502810185019093528083528493830182828015612cb957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612c9b575b505050505090506000915060005b815181101561293757818181518110612ce257612ce2613f14565b60209081029190910101516040516379c1291760e01b81526001600160a01b0387811660048301528681166024830152909116906379c1291790604401602060405180830381865afa158015612d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d609190614335565b612d6a9084613fb3565b9250600101612cc7565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907ff10a1acd40d60bee3d5b658d910c1f9ab77a0fe972c5de7774cd8404d65bc66990600090a35050565b6000612dd1846130e1565b9050612de86001600160a01b03851684308561314c565b6000612df3856130e1565b905082612e008383613f40565b14610bde5760405162461bcd60e51b815260206004820152601560248201527411125117d393d517d49150d152559157d1561050d5605a1b60448201526064016109f3565b612e508484846131b3565b826001600160a01b0316846001600160a01b03168888604051612e74929190613f69565b604080519182900382206001600160a01b0386168352602083018a9052908201869052907fae2504b8c277e24642789ad5fb484179bdb5a5f4dc86b63f89e21788677f3c109060600160405180910390a450505050505050565b6000808211612ee557612ee0846130e1565b612ee7565b815b9050612ef484848361307d565b826001600160a01b0316846001600160a01b03167fd092d7fceb5ea5a962639fcc27a7bb315e7637e699e3b108cd570c38c758430083604051612f3991815260200190565b60405180910390a350505050565b60006001600160a01b038216612f9f5760405162461bcd60e51b815260206004820152601760248201527f43414e4e4f545f44495350454e53455f544f5f5a45524f00000000000000000060448201526064016109f3565b506001600160a01b038084166000818152600460209081526040808320948716835293815283822080549083905592825260039052918220805491928392612fe8908490613f40565b90915550612ffa90508484848461327b565b61300584838361307d565b816001600160a01b0316836001600160a01b0316856001600160a01b03167f365c82a2bdc395fa2c986a8aa602cb7c0d691b728b80765d104b8a879b3b484f8460405161305491815260200190565b60405180910390a49392505050565b6000613070848484613318565b90506117f48383836131b3565b610a586001600160a01b038416838361346a565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015613128573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6a9190614335565b6040516001600160a01b03848116602483015283811660448301526064820183905261136f9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505061349b565b6001600160a01b0380841660009081526004602090815260408083209386168352929052908120546131e6908390613fb3565b6001600160a01b0385166000908152600360205260408120549192509061320e908490613fb3565b6001600160a01b038681166000818152600460209081526040808320948a1680845294825280832088905583835260038252918290208590559051878152939450919290917fd6f1b1200b83332fb4d7e0f91e1f1672c77bb36ac9954f1b998d48f1a155434e9101612872565b816001600160a01b0316836001600160a01b0316036132d6576001600160a01b038085166000908152600f60209081526040808320938716835292905290812080548392906132cb908490613fb3565b9091555061136f9050565b6001600160a01b0380851660009081526010602090815260408083209387168352929052908120805483929061330d908490613fb3565b909155505050505050565b6001600160a01b03808316600090815260086020908152604080832093871683529290529081205460ff166133815760405162461bcd60e51b815260206004820152600f60248201526e4e4f545f50554c4c5f534f5552434560881b60448201526064016109f3565b600061338c846130e1565b6040516272333d60e01b81526001600160a01b0386811660048301528581166024830152919250908616906272333d90604401600060405180830381600087803b1580156133d957600080fd5b505af11580156133ed573d6000803e3d6000fd5b5050505060006133fc856130e1565b90506134088282613f40565b9250856001600160a01b0316846001600160a01b0316866001600160a01b03167f1d52d80be7a2d094505cdf4bcddcc841ac4ffde4ab097d1c8c80d431fd7ee0d38660405161345991815260200190565b60405180910390a450509392505050565b6040516001600160a01b03838116602483015260448201839052610a5891859182169063a9059cbb90606401613181565b60006134b06001600160a01b038416836134fe565b905080516000141580156134d55750808060200190518101906134d39190614267565b155b15610a5857604051635274afe760e01b81526001600160a01b03841660048201526024016109f3565b60606117f48383600084600080856001600160a01b03168486604051613524919061434e565b60006040518083038185875af1925050503d8060008114613561576040519150601f19603f3d011682016040523d82523d6000602084013e613566565b606091505b5091509150613576868383613580565b9695505050505050565b60608261359557613590826135dc565b6117f4565b81511580156135ac57506001600160a01b0384163b155b156135d557604051639996b31560e01b81526001600160a01b03851660048201526024016109f3565b50806117f4565b8051156135ec5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50805461361190613f79565b6000825580601f10613621575050565b601f0160209004906000526020600020908101906117b591905b8082111561364f576000815560010161363b565b5090565b80356001600160a01b038116811461366a57600080fd5b919050565b60006020828403121561368157600080fd5b6117f482613653565b6000806040838503121561369d57600080fd5b6136a683613653565b91506136b460208401613653565b90509250929050565b6020808252825182820181905260009190848201906040850190845b818110156136fe5783516001600160a01b0316835292840192918401916001016136d9565b50909695505050505050565b60008083601f84011261371c57600080fd5b5081356001600160401b0381111561373357600080fd5b6020830191508360208260051b850101111561374e57600080fd5b9250929050565b6000806000806060858703121561376b57600080fd5b61377485613653565b935061378260208601613653565b925060408501356001600160401b0381111561379d57600080fd5b6137a98782880161370a565b95989497509550505050565b6000602082840312156137c757600080fd5b5035919050565b60008083601f8401126137e057600080fd5b5081356001600160401b038111156137f757600080fd5b60208301915083602082850101111561374e57600080fd5b60008060008060008060006080888a03121561382a57600080fd5b87356001600160401b038082111561384157600080fd5b61384d8b838c016137ce565b909950975087915061386160208b01613653565b965060408a013591508082111561387757600080fd5b6138838b838c016137ce565b909650945060608a013591508082111561389c57600080fd5b506138a98a828b016137ce565b989b979a50959850939692959293505050565b6000806000604084860312156138d157600080fd5b83356001600160401b038111156138e757600080fd5b6138f3868287016137ce565b9094509250613906905060208501613653565b90509250925092565b60005b8381101561392a578181015183820152602001613912565b50506000910152565b6000815180845261394b81602086016020860161390f565b601f01601f19169290920160200192915050565b6040815260006139726040830185613933565b82810360208401526139848185613933565b95945050505050565b600080604083850312156139a057600080fd5b6139a983613653565b946020939093013593505050565b6020815260006117f46020830184613933565b6000806000606084860312156139df57600080fd5b6139e884613653565b92506139f660208501613653565b9150604084013560028110613a0a57600080fd5b809150509250925092565b60008060008060808587031215613a2b57600080fd5b613a3485613653565b9350613a4260208601613653565b925060408501359150613a5760608601613653565b905092959194509250565b634e487b7160e01b600052602160045260246000fd5b6020810160028310613a9a57634e487b7160e01b600052602160045260246000fd5b91905290565b80151581146117b557600080fd5b600060208284031215613ac057600080fd5b81356117f481613aa0565b600080600060408486031215613ae057600080fd5b613ae984613653565b925060208401356001600160401b03811115613b0457600080fd5b613b108682870161370a565b9497909650939450505050565b6020808252825182820181905260009190848201906040850190845b818110156136fe57835183529284019291840191600101613b39565b60008060008060008060808789031215613b6e57600080fd5b613b7787613653565b955060208701356001600160401b0380821115613b9357600080fd5b613b9f8a838b0161370a565b90975095506040890135915080821115613bb857600080fd5b50613bc589828a0161370a565b9094509250613bd8905060608801613653565b90509295509295509295565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215613c0d57600080fd5b613c1683613653565b915060208301356001600160401b0380821115613c3257600080fd5b818501915085601f830112613c4657600080fd5b813581811115613c5857613c58613be4565b604051601f8201601f19908116603f01168101908382118183101715613c8057613c80613be4565b81604052828152886020848701011115613c9957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613d1257603f19888603018452613d00858351613933565b94509285019290850190600101613ce4565b5092979650505050505050565b60008060008060008060a08789031215613d3857600080fd5b86356001600160401b03811115613d4e57600080fd5b613d5a89828a016137ce565b90975095505060208701359350613d7360408801613653565b9250613d8160608801613653565b9150608087013590509295509295509295565b60008060008060008060008060a0898b031215613db057600080fd5b88356001600160401b0380821115613dc757600080fd5b613dd38c838d016137ce565b909a50985060208b01359750889150613dee60408c01613653565b965060608b0135915080821115613e0457600080fd5b613e108c838d0161370a565b909650945060808b0135915080821115613e2957600080fd5b50613e368b828c0161370a565b999c989b5096995094979396929594505050565b60008060408385031215613e5d57600080fd5b613e6683613653565b91506020830135613e7681613aa0565b809150509250929050565b60208082526013908201527210531317d0d3105253525391d7d4105554d151606a1b604082015260600190565b60208082526019908201527f434c41494d494e475f5041555345445f464f525f544f4b454e00000000000000604082015260600190565b602080825260159082015274141554d2115497d393d517d49151d254d511549151605a1b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115610f6a57610f6a613f2a565b634e487b7160e01b600052603160045260246000fd5b8183823760009101908152919050565b600181811c90821680613f8d57607f821691505b602082108103613fad57634e487b7160e01b600052602260045260246000fd5b50919050565b80820180821115610f6a57610f6a613f2a565b601f821115610a58576000816000526020600020601f850160051c81016020861015613fef5750805b601f850160051c820191505b8181101561400e57828155600101613ffb565b505050505050565b600019600383901b1c191660019190911b1790565b6001600160401b0383111561404257614042613be4565b614056836140508354613f79565b83613fc6565b6000601f84116001811461408457600085156140725750838201355b61407c8682614016565b845550610bde565b600083815260209020601f19861690835b828110156140b55786850135825560209485019460019092019101614095565b50868210156140d25760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208082526018908201527f4e4f545f4f4e474f494e475f44495350454e534154494f4e0000000000000000604082015260600190565b600080835461412981613f79565b60018281168015614141576001811461415657614185565b60ff1984168752821515830287019450614185565b8760005260208060002060005b8581101561417c5781548a820152908401908201614163565b50505082870194505b50929695505050505050565b81810361419c575050565b6141a68254613f79565b6001600160401b038111156141bd576141bd613be4565b6141d1816141cb8454613f79565b84613fc6565b6000601f8211600181146141ff57600083156141ed5750848201545b6141f78482614016565b855550610bde565b600085815260209020601f19841690600086815260209020845b838110156142395782860154825560019586019590910190602001614219565b50858310156142575781850154600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561427957600080fd5b81516117f481613aa0565b81516001600160401b0381111561429d5761429d613be4565b6142ab816141cb8454613f79565b602080601f8311600181146142da57600084156142c85750858301515b6142d28582614016565b86555061400e565b600085815260208120601f198616915b82811015614309578886015182559484019460019091019084016142ea565b508582101561425757939096015160001960f8600387901b161c19169092555050600190811b01905550565b60006020828403121561434757600080fd5b5051919050565b6000825161436081846020870161390f565b919091019291505056fea2646970667358221220882c27ef62090255e612daffa5cfd82f9b3605233ffeaccb0eec03330736d58b64736f6c63430008180033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103975760003560e01c806379ba5097116101e9578063b7b6287e1161010f578063e30c3978116100ad578063f3695d981161007c578063f3695d98146108c8578063f44978f914610949578063f5f5ba721461095c578063ffb85f5a1461098f57600080fd5b8063e30c3978146108e2578063e50c26b9146108f3578063e9597a8b14610916578063f2fde38b1461093657600080fd5b8063b987b2e8116100e9578063b987b2e814610887578063cc236cc7146108b5578063d1a8ff54146108c8578063dec66036146108cf57600080fd5b8063b7b6287e14610859578063b836441e1461086c578063b8b65cf41461087457600080fd5b80638da5cb5b116101875780639d8ec144116101565780639d8ec144146107e8578063a8bc01a4146107fb578063a9b8c5b41461081b578063b058fa361461084657600080fd5b80638da5cb5b146107a45780638e681ec3146107b55780638e96317f146107c85780639553c578146107db57600080fd5b806386725a75116101c357806386725a7514610720578063874951c3146107335780638aa10435146107725780638bf4d4af1461079157600080fd5b806379ba5097146106f257806379c12917146106fa57806385f9db671461070d57600080fd5b8063330ca298116102ce5780635b2e448f1161026c5780636a274d221161023b5780636a274d221461068c578063715018a6146106b757806374b3ff4f146106bf5780637820c216146106df57600080fd5b80635b2e448f14610602578063614d08f814610615578063647aefbd1461064b578063677625a71461067957600080fd5b806342456d0d116102a857806342456d0d146105805780634b98684f146105935780634eb4164c146105a657806352fc7984146105b957600080fd5b8063330ca2981461051d57806336fa5f081461053e57806338b903331461055157600080fd5b80631a6748f41161033b57806323e86e341161031557806323e86e34146104c1578063247858ba146104d45780632d7ce37f146104e75780632eb37ff4146104fa57600080fd5b80631a6748f414610470578063213e832814610483578063231d89c8146104ae57600080fd5b80630dd7b0cb116103775780630dd7b0cb146104225780630e6adf37146104355780630eceebc51461044a57806311bb93511461045d57600080fd5b80626dff4b1461039c57806272333d146103d4578063099b58fd146103e9575b600080fd5b6103bf6103aa36600461366f565b600d6020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6103e76103e236600461368a565b6109a2565b005b6104146103f736600461368a565b600f60209081526000928352604080842090915290825290205481565b6040519081526020016103cb565b6103e761043036600461368a565b610a5d565b61043d610ac5565b6040516103cb91906136bd565b6103e7610458366004613755565b610b27565b61043d61046b36600461366f565b610be5565b6103e761047e36600461368a565b610c5b565b6104966104913660046137b5565b610e10565b6040516001600160a01b0390911681526020016103cb565b61043d6104bc36600461366f565b610e3a565b6103e76104cf36600461380f565b610eae565b600254610496906001600160a01b031681565b6104146104f536600461368a565b610f35565b6103bf61050836600461366f565b60066020526000908152604090205460ff1681565b61053061052b3660046138bc565b610f70565b6040516103cb92919061395f565b61049661054c36600461398d565b611113565b6105736040518060400160405280600381526020016203130360ec1b81525081565b6040516103cb91906139b7565b6103e761058e36600461368a565b61114b565b6103e76105a13660046139ca565b6111be565b6103e76105b4366004613a15565b61135b565b6105f56105c736600461368a565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205460ff1690565b6040516103cb9190613a78565b6103e761061036600461368a565b611375565b6105736040518060400160405280601781526020017647656e6572616c546f6b656e44697370656e736572563160481b81525081565b6103bf61065936600461368a565b600860209081526000928352604080842090915290825290205460ff1681565b6103e7610687366004613aae565b611559565b61041461069a36600461368a565b601060209081526000928352604080842090915290825290205481565b6103e76115ee565b6106d26106cd366004613acb565b611602565b6040516103cb9190613b1d565b6104966106ed36600461398d565b611758565b6103e7611774565b61041461070836600461368a565b6117b8565b6103e761071b366004613b55565b6117fb565b6103e761072e36600461366f565b6118a1565b6103bf610741366004613bfa565b6012602090815260009283526040909220815180830184018051928152908401929093019190912091525460ff1681565b60408051808201909152600381526203130360ec1b6020820152610573565b61057361079f366004613bfa565b6118b2565b6000546001600160a01b0316610496565b6103e76107c336600461380f565b611968565b6103e76107d63660046138bc565b611b32565b6005546103bf9060ff1681565b6105736107f636600461398d565b611d77565b61080e61080936600461366f565b611daf565b6040516103cb9190613cbb565b61041461082936600461368a565b600460209081526000928352604080842090915290825290205481565b6103e7610854366004613d1f565b611e9e565b6104966108673660046137b5565b611f75565b61043d611f85565b610573610882366004613bfa565b611fe5565b6105f561089536600461368a565b600a60209081526000928352604080842090915290825290205460ff1681565b6103e76108c3366004613d94565b61201a565b60016103bf565b6103e76108dd36600461398d565b6121cb565b6001546001600160a01b0316610496565b6103bf61090136600461366f565b600e6020526000908152604090205460ff1681565b61041461092436600461366f565b60036020526000908152604090205481565b6103e761094436600461366f565b6121f3565b6103e7610957366004613e4a565b612264565b60408051808201909152601781527647656e6572616c546f6b656e44697370656e736572563160481b6020820152610573565b6103e761099d36600461368a565b612324565b6002546001600160a01b031633146109fc5760405162461bcd60e51b81526020600482015260186024820152772727aa2fa227aba729aa2922a0a6afa224a9a822a729a2a960411b60448201526064015b60405180910390fd5b6002546001600160a01b0316610a4e5760405162461bcd60e51b81526020600482015260176024820152762727afa227aba729aa2922a0a6afa224a9a822a729a2a960491b60448201526064016109f3565b610a588282612526565b505050565b600554829060ff1615610a825760405162461bcd60e51b81526004016109f390613e81565b6001600160a01b03811660009081526006602052604090205460ff1615610abb5760405162461bcd60e51b81526004016109f390613eae565b610a58838361254c565b6060600c805480602002602001604051908101604052809291908181526020018280548015610b1d57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610aff575b5050505050905090565b600554849060ff1615610b4c5760405162461bcd60e51b81526004016109f390613e81565b6001600160a01b03811660009081526006602052604090205460ff1615610b855760405162461bcd60e51b81526004016109f390613eae565b81610bc85760405162461bcd60e51b81526020600482015260136024820152721393d7d4d3d55490d154d7d41493d592511151606a1b60448201526064016109f3565b610bd483838787612557565b610bde858561254c565b5050505050565b6001600160a01b038116600090815260096020908152604091829020805483518184028101840190945280845260609392830182828015610c4f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c31575b50505050509050919050565b610c6361259c565b610c6d82826125c9565b610c895760405162461bcd60e51b81526004016109f390613ee5565b6001600160a01b038281166000818152600a602090815260408083209486168352938152838220805460ff191690559181526009909152908120905b8154811015610dc157826001600160a01b0316828281548110610cea57610cea613f14565b6000918252602090912001546001600160a01b031603610db95781548290610d1490600190613f40565b81548110610d2457610d24613f14565b9060005260206000200160009054906101000a90046001600160a01b0316828281548110610d5457610d54613f14565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081805480610d9257610d92613f53565b600082815260209020810160001990810180546001600160a01b0319169055019055610dc1565b600101610cc5565b50610dcb83612611565b816001600160a01b0316836001600160a01b03167f5144cb6540b0046ea54d1878787028f5635d75813e2aaf25ea0904fc69f47e3360405160405180910390a3505050565b600b8181548110610e2057600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b038116600090815260076020908152604091829020805483518184028101840190945280845260609392830182828015610c4f576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610c315750505050509050919050565b610eb661259c565b610f2c87878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8b01819004810282018101909252898152925089915088908190840183828082843760009201919091525061279192505050565b50505050505050565b6000610f418383612881565b50506001600160a01b038083166000908152600460209081526040808320938516835292905220545b92915050565b6001600160a01b0381166000908152601360205260409081902090516060918291610f9e9087908790613f69565b908152602001604051809103902060146000856001600160a01b03166001600160a01b031681526020019081526020016000208686604051610fe1929190613f69565b9081526020016040518091039020818054610ffb90613f79565b80601f016020809104026020016040519081016040528092919081815260200182805461102790613f79565b80156110745780601f1061104957610100808354040283529160200191611074565b820191906000526020600020905b81548152906001019060200180831161105757829003601f168201915b5050505050915080805461108790613f79565b80601f01602080910402602001604051908101604052809291908181526020018280546110b390613f79565b80156111005780601f106110d557610100808354040283529160200191611100565b820191906000526020600020905b8154815290600101906020018083116110e357829003601f168201915b5050505050905091509150935093915050565b6007602052816000526040600020818154811061112f57600080fd5b6000918252602090912001546001600160a01b03169150829050565b600554829060ff16156111705760405162461bcd60e51b81526004016109f390613e81565b6001600160a01b03811660009081526006602052604090205460ff16156111a95760405162461bcd60e51b81526004016109f390613eae565b6111b38383612881565b50610a58838361254c565b6111c661259c565b6111d083836125c9565b1561121d5760405162461bcd60e51b815260206004820152601960248201527f5055534845525f414c52454144595f524547495354455245440000000000000060448201526064016109f3565b600081600181111561123157611231613a62565b0361127e5760405162461bcd60e51b815260206004820152601a60248201527f43414e4e4f545f52454749535445525f4e4f4e455f4c4556454c00000000000060448201526064016109f3565b6001600160a01b038084166000908152600a60209081526040808320938616835292905220805482919060ff1916600183818111156112bf576112bf613a62565b02179055506001600160a01b0383811660009081526009602090815260408220805460018101825590835291200180546001600160a01b03191691841691909117905561130b8361293f565b816001600160a01b0316836001600160a01b03167f196fa3ab7946db556eb94c3423dc51d780f3a397bcaecd284b44456dc88324d98360405161134e9190613a78565b60405180910390a3505050565b61136361259c565b61136f84848484612aa7565b50505050565b61137d61259c565b6001600160a01b0382166000908152600760205260408120815b815481101561149757836001600160a01b03168282815481106113bc576113bc613f14565b6000918252602090912001546001600160a01b03160361148f57815482906113e690600190613f40565b815481106113f6576113f6613f14565b9060005260206000200160009054906101000a90046001600160a01b031682828154811061142657611426613f14565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508180548061146457611464613f53565b600082815260209020810160001990810180546001600160a01b031916905501905560019250611497565b600101611397565b50816114dd5760405162461bcd60e51b81526020600482015260156024820152741415531317d4d3d55490d157d393d517d193d55391605a1b60448201526064016109f3565b6001600160a01b038085166000908152600860209081526040808320938716835292905220805460ff1916905561151384612611565b826001600160a01b0316846001600160a01b03167f493b1bf532df7004894c240578a101f10cbb9216cc9b787dbe3cd9a81b52c4e460405160405180910390a350505050565b61156161259c565b60055481151560ff9091161515036115a95760405162461bcd60e51b815260206004820152600b60248201526a1053149150511657d4d15560aa1b60448201526064016109f3565b6005805460ff191682151590811790915560405160ff9091161515907fa042e27caefe535b8657a25f0d53a680853b51681d7d510291f72ab708b72bf090600090a250565b6115f661259c565b6116006000612c39565b565b6002546060906001600160a01b0316331461165a5760405162461bcd60e51b81526020600482015260186024820152772727aa2fa227aba729aa2922a0a6afa224a9a822a729a2a960411b60448201526064016109f3565b6002546001600160a01b03166116ac5760405162461bcd60e51b81526020600482015260176024820152762727afa227aba729aa2922a0a6afa224a9a822a729a2a960491b60448201526064016109f3565b816001600160401b038111156116c4576116c4613be4565b6040519080825280602002602001820160405280156116ed578160200160208202803683370190505b50905060005b828110156117505761172b8585858481811061171157611711613f14565b9050602002016020810190611726919061366f565b612526565b82828151811061173d5761173d613f14565b60209081029190910101526001016116f3565b509392505050565b6009602052816000526040600020818154811061112f57600080fd5b60015433906001600160a01b031681146117ac5760405163118cdaa760e01b81526001600160a01b03821660048201526024016109f3565b6117b581612c39565b50565b60006117c48383612c52565b6001600160a01b038085166000908152600460209081526040808320938716835292905220546117f49190613fb3565b9392505050565b61180361259c565b8382146118445760405162461bcd60e51b815260206004820152600f60248201526e0988a9c8ea890be9a92a69a82a8869608b1b60448201526064016109f3565b60005b84811015610f2c576118998787878481811061186557611865613f14565b905060200201602081019061187a919061366f565b86868581811061188c5761188c613f14565b9050602002013585612aa7565b600101611847565b6118a961259c565b6117b581612d74565b60146020908152600092835260409092208151808301840180519281529084019290930191909120915280546118e790613f79565b80601f016020809104026020016040519081016040528092919081815260200182805461191390613f79565b80156119605780601f1061193557610100808354040283529160200191611960565b820191906000526020600020905b81548152906001019060200180831161194357829003601f168201915b505050505081565b61197061259c565b6001600160a01b0385166000908152601260205260409081902090516119999089908990613f69565b9081526040519081900360200190205460ff16156119eb5760405162461bcd60e51b815260206004820152600f60248201526e414c52454144595f4f4e474f494e4760881b60448201526064016109f3565b6001600160a01b03851660009081526012602052604090819020905160019190611a18908a908a90613f69565b9081526040805160209281900383019020805460ff1916931515939093179092556001600160a01b0387166000908152601182529182208054600181018255908352912001611a6887898361402b565b50611adf87878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8b01819004810282018101909252898152925089915088908190840183828082843760009201919091525061279192505050565b846001600160a01b03168787604051611af9929190613f69565b604051908190038120907f2a9b4fc367f7e38f84011e08df7345c49bc5ab25bf5a6fa7a1c7c02f592ba8e490600090a350505050505050565b611b3a61259c565b6001600160a01b038116600090815260126020526040908190209051611b639085908590613f69565b9081526040519081900360200190205460ff16611b925760405162461bcd60e51b81526004016109f3906140e4565b6001600160a01b0381166000908152601260205260408082209051611bba9086908690613f69565b9081526040805160209281900383019020805460ff1916931515939093179092556001600160a01b03831660009081526011909152908120905b8154811015611cfb578484604051602001611c10929190613f69565b60405160208183030381529060405280519060200120828281548110611c3857611c38613f14565b90600052602060002001604051602001611c52919061411b565b6040516020818303038152906040528051906020012003611cf35781548290611c7d90600190613f40565b81548110611c8d57611c8d613f14565b90600052602060002001828281548110611ca957611ca9613f14565b906000526020600020019081611cbf9190614191565b5081805480611cd057611cd0613f53565b600190038181906000526020600020016000611cec9190613605565b9055611cfb565b600101611bf4565b50611d278484846040518060200160405280600081525060405180602001604052806000815250612791565b816001600160a01b03168484604051611d41929190613f69565b604051908190038120907fab45c658146b5490390503d9570ee0393d223a399a8b147e4a31f164e6b3dab890600090a350505050565b60116020528160005260406000208181548110611d9357600080fd5b906000526020600020016000915091505080546118e790613f79565b6001600160a01b0381166000908152601160209081526040808320805482518185028101850190935280835260609492939192909184015b82821015611e93578382906000526020600020018054611e0690613f79565b80601f0160208091040260200160405190810160405280929190818152602001828054611e3290613f79565b8015611e7f5780601f10611e5457610100808354040283529160200191611e7f565b820191906000526020600020905b815481529060010190602001808311611e6257829003601f168201915b505050505081526020019060010190611de7565b505050509050919050565b33611ea984826125c9565b611ec55760405162461bcd60e51b81526004016109f390613ee5565b6001600160a01b038416600090815260126020526040908190209051611eee9089908990613f69565b9081526040519081900360200190205460ff16611f1d5760405162461bcd60e51b81526004016109f3906140e4565b60008211611f5b5760405162461bcd60e51b815260206004820152600b60248201526a414d4f554e545f5a45524f60a81b60448201526064016109f3565b611f66843384612dc6565b610f2c87878787878787612e45565b600c8181548110610e2057600080fd5b6060600b805480602002602001604051908101604052809291908181526020018280548015610b1d576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610aff575050505050905090565b60136020908152600092835260409092208151808301840180519281529084019290930191909120915280546118e790613f79565b82811461205b5760405162461bcd60e51b815260206004820152600f60248201526e0988a9c8ea890be9a92a69a82a8869608b1b60448201526064016109f3565b3361206686826125c9565b6120825760405162461bcd60e51b81526004016109f390613ee5565b6001600160a01b0386166000908152601260205260409081902090516120ab908b908b90613f69565b9081526040519081900360200190205460ff166120da5760405162461bcd60e51b81526004016109f3906140e4565b6000805b85811015612114578484828181106120f8576120f8613f14565b905060200201358261210a9190613fb3565b91506001016120de565b50600081116121535760405162461bcd60e51b815260206004820152600b60248201526a414d4f554e545f5a45524f60a81b60448201526064016109f3565b61215e878383612dc6565b60005b858110156121be576121b68b8b8b8b8b8b8781811061218257612182613f14565b9050602002016020810190612197919061366f565b8a8a888181106121a9576121a9613f14565b9050602002013589612e45565b600101612161565b5050505050505050505050565b6121d361259c565b6121ef826121e96000546001600160a01b031690565b83612ece565b5050565b6121fb61259c565b600180546001600160a01b0383166001600160a01b0319909116811790915561222c6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b61226c61259c565b6001600160a01b03821660009081526006602052604090205481151560ff9091161515036122ca5760405162461bcd60e51b815260206004820152600b60248201526a1053149150511657d4d15560aa1b60448201526064016109f3565b6001600160a01b038216600081815260066020526040808220805460ff1916851515908117909155905160ff909116151592917fe766dd0694ff9295340d29c34dbc30b4f70c083307c3c81e5285dba3c073274991a35050565b61232c61259c565b806001600160a01b031663f3695d986040518163ffffffff1660e01b8152600401602060405180830381865afa15801561236a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238e9190614267565b6123cf5760405162461bcd60e51b81526020600482015260126024820152714e4f545f50554c4c5f534f555243455f563160701b60448201526064016109f3565b6001600160a01b0382166000908152600760205260408120905b815481101561247857826001600160a01b031682828154811061240e5761240e613f14565b6000918252602090912001546001600160a01b0316036124705760405162461bcd60e51b815260206004820152601960248201527f50554c4c5f534f555243455f414c52454144595f41444445440000000000000060448201526064016109f3565b6001016123e9565b506001600160a01b0383811660008181526007602090815260408083208054600180820183559185528385200180546001600160a01b03191696891696871790559383526008825280832094835293905291909120805460ff191690911790556124e18361293f565b816001600160a01b0316836001600160a01b03167f46f9eb8ce96dd38714a7b9ac42bdc69a3313c60e548cf5ef032570b793045fdd60405160405180910390a3505050565b60006125328383612881565b506002546117f490849084906001600160a01b0316612f47565b610a58828283612f47565b60005b83811015610bde5761259385858381811061257757612577613f14565b905060200201602081019061258c919061366f565b8484613063565b5060010161255a565b6000546001600160a01b031633146116005760405163118cdaa760e01b81523360048201526024016109f3565b6001600160a01b038083166000908152600a6020908152604080832093851683529290529081205460ff168181600181111561260757612607613a62565b1415949350505050565b6001600160a01b03811660009081526007602090815260408083205460099092529091205481158015612642575080155b15610a585760005b600b5481101561274557836001600160a01b0316600b828154811061267157612671613f14565b6000918252602090912001546001600160a01b03160361273d57600b805461269b90600190613f40565b815481106126ab576126ab613f14565b600091825260209091200154600b80546001600160a01b0390921691839081106126d7576126d7613f14565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600b80548061271657612716613f53565b600082815260209020810160001990810180546001600160a01b0319169055019055612745565b60010161264a565b506001600160a01b0383166000818152600e6020526040808220805460ff19169055517f5458626fa48fdcbb7a33a1f144e182222b16ecfdd862b844752fc0061c55b45a9190a2505050565b6001600160a01b0383166000908152601360205260409081902090518391906127bd9088908890613f69565b908152602001604051809103902090816127d79190614284565b506001600160a01b0383166000908152601460205260409081902090518291906128049088908890613f69565b9081526020016040518091039020908161281e9190614284565b50826001600160a01b03168585604051612839929190613f69565b60405180910390207f6580caef4438dbfe0b139727fbf172f51a284bf6e86fca731f02eea21ca58097848460405161287292919061395f565b60405180910390a35050505050565b6001600160a01b0382166000908152600760209081526040808320805482518185028101850190935280835284938301828280156128e857602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116128ca575b505050505090506000915060005b81518110156129375761292382828151811061291457612914613f14565b60200260200101518686613063565b61292d9084613fb3565b92506001016128f6565b505092915050565b6001600160a01b0381166000908152600e602052604090205460ff168015612965575050565b6001600160a01b0382166000908152600d602052604090205460ff16612a1257600c805460018082019092557fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b0319166001600160a01b0385169081179091556000818152600d6020526040808220805460ff1916909417909355915190917ffef74848d3638a6ed3547447282ce33584cf17be953e3f9f7c6824e2284969e991a25b806121ef57600b805460018082019092557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b0319166001600160a01b0385169081179091556000818152600e6020526040808220805460ff1916909417909355915190917f74e2d6b252841daa9d389cafd5dca3a3927ef59ebfa28699c1748c1a1603250e91a25050565b612ab18484612881565b506001600160a01b03808516600090815260046020908152604080832093871683529290529081205490838103612b1157506001600160a01b03808616600090815260046020908152604080832093881683529290529081205580612b8d565b83821015612b5a5760405162461bcd60e51b8152602060048201526016602482015275414d4f554e545f455843454544535f50454e44494e4760501b60448201526064016109f3565b612b648483613f40565b6001600160a01b038088166000908152600460209081526040808320938a168352929052205550825b6001600160a01b038616600090815260036020526040902054808211612bbc57612bb78282613f40565b612bbf565b60005b6001600160a01b038816600090815260036020526040902055612be387858461307d565b856001600160a01b0316876001600160a01b03167f13268b3f271140c93c5d8b166950c19ad5320c82e78b1aa918bfb842ff13454584604051612c2891815260200190565b60405180910390a350505050505050565b600180546001600160a01b03191690556117b581613091565b6001600160a01b038216600090815260076020908152604080832080548251818502810185019093528083528493830182828015612cb957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612c9b575b505050505090506000915060005b815181101561293757818181518110612ce257612ce2613f14565b60209081029190910101516040516379c1291760e01b81526001600160a01b0387811660048301528681166024830152909116906379c1291790604401602060405180830381865afa158015612d3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d609190614335565b612d6a9084613fb3565b9250600101612cc7565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907ff10a1acd40d60bee3d5b658d910c1f9ab77a0fe972c5de7774cd8404d65bc66990600090a35050565b6000612dd1846130e1565b9050612de86001600160a01b03851684308561314c565b6000612df3856130e1565b905082612e008383613f40565b14610bde5760405162461bcd60e51b815260206004820152601560248201527411125117d393d517d49150d152559157d1561050d5605a1b60448201526064016109f3565b612e508484846131b3565b826001600160a01b0316846001600160a01b03168888604051612e74929190613f69565b604080519182900382206001600160a01b0386168352602083018a9052908201869052907fae2504b8c277e24642789ad5fb484179bdb5a5f4dc86b63f89e21788677f3c109060600160405180910390a450505050505050565b6000808211612ee557612ee0846130e1565b612ee7565b815b9050612ef484848361307d565b826001600160a01b0316846001600160a01b03167fd092d7fceb5ea5a962639fcc27a7bb315e7637e699e3b108cd570c38c758430083604051612f3991815260200190565b60405180910390a350505050565b60006001600160a01b038216612f9f5760405162461bcd60e51b815260206004820152601760248201527f43414e4e4f545f44495350454e53455f544f5f5a45524f00000000000000000060448201526064016109f3565b506001600160a01b038084166000818152600460209081526040808320948716835293815283822080549083905592825260039052918220805491928392612fe8908490613f40565b90915550612ffa90508484848461327b565b61300584838361307d565b816001600160a01b0316836001600160a01b0316856001600160a01b03167f365c82a2bdc395fa2c986a8aa602cb7c0d691b728b80765d104b8a879b3b484f8460405161305491815260200190565b60405180910390a49392505050565b6000613070848484613318565b90506117f48383836131b3565b610a586001600160a01b038416838361346a565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015613128573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6a9190614335565b6040516001600160a01b03848116602483015283811660448301526064820183905261136f9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505061349b565b6001600160a01b0380841660009081526004602090815260408083209386168352929052908120546131e6908390613fb3565b6001600160a01b0385166000908152600360205260408120549192509061320e908490613fb3565b6001600160a01b038681166000818152600460209081526040808320948a1680845294825280832088905583835260038252918290208590559051878152939450919290917fd6f1b1200b83332fb4d7e0f91e1f1672c77bb36ac9954f1b998d48f1a155434e9101612872565b816001600160a01b0316836001600160a01b0316036132d6576001600160a01b038085166000908152600f60209081526040808320938716835292905290812080548392906132cb908490613fb3565b9091555061136f9050565b6001600160a01b0380851660009081526010602090815260408083209387168352929052908120805483929061330d908490613fb3565b909155505050505050565b6001600160a01b03808316600090815260086020908152604080832093871683529290529081205460ff166133815760405162461bcd60e51b815260206004820152600f60248201526e4e4f545f50554c4c5f534f5552434560881b60448201526064016109f3565b600061338c846130e1565b6040516272333d60e01b81526001600160a01b0386811660048301528581166024830152919250908616906272333d90604401600060405180830381600087803b1580156133d957600080fd5b505af11580156133ed573d6000803e3d6000fd5b5050505060006133fc856130e1565b90506134088282613f40565b9250856001600160a01b0316846001600160a01b0316866001600160a01b03167f1d52d80be7a2d094505cdf4bcddcc841ac4ffde4ab097d1c8c80d431fd7ee0d38660405161345991815260200190565b60405180910390a450509392505050565b6040516001600160a01b03838116602483015260448201839052610a5891859182169063a9059cbb90606401613181565b60006134b06001600160a01b038416836134fe565b905080516000141580156134d55750808060200190518101906134d39190614267565b155b15610a5857604051635274afe760e01b81526001600160a01b03841660048201526024016109f3565b60606117f48383600084600080856001600160a01b03168486604051613524919061434e565b60006040518083038185875af1925050503d8060008114613561576040519150601f19603f3d011682016040523d82523d6000602084013e613566565b606091505b5091509150613576868383613580565b9695505050505050565b60608261359557613590826135dc565b6117f4565b81511580156135ac57506001600160a01b0384163b155b156135d557604051639996b31560e01b81526001600160a01b03851660048201526024016109f3565b50806117f4565b8051156135ec5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50805461361190613f79565b6000825580601f10613621575050565b601f0160209004906000526020600020908101906117b591905b8082111561364f576000815560010161363b565b5090565b80356001600160a01b038116811461366a57600080fd5b919050565b60006020828403121561368157600080fd5b6117f482613653565b6000806040838503121561369d57600080fd5b6136a683613653565b91506136b460208401613653565b90509250929050565b6020808252825182820181905260009190848201906040850190845b818110156136fe5783516001600160a01b0316835292840192918401916001016136d9565b50909695505050505050565b60008083601f84011261371c57600080fd5b5081356001600160401b0381111561373357600080fd5b6020830191508360208260051b850101111561374e57600080fd5b9250929050565b6000806000806060858703121561376b57600080fd5b61377485613653565b935061378260208601613653565b925060408501356001600160401b0381111561379d57600080fd5b6137a98782880161370a565b95989497509550505050565b6000602082840312156137c757600080fd5b5035919050565b60008083601f8401126137e057600080fd5b5081356001600160401b038111156137f757600080fd5b60208301915083602082850101111561374e57600080fd5b60008060008060008060006080888a03121561382a57600080fd5b87356001600160401b038082111561384157600080fd5b61384d8b838c016137ce565b909950975087915061386160208b01613653565b965060408a013591508082111561387757600080fd5b6138838b838c016137ce565b909650945060608a013591508082111561389c57600080fd5b506138a98a828b016137ce565b989b979a50959850939692959293505050565b6000806000604084860312156138d157600080fd5b83356001600160401b038111156138e757600080fd5b6138f3868287016137ce565b9094509250613906905060208501613653565b90509250925092565b60005b8381101561392a578181015183820152602001613912565b50506000910152565b6000815180845261394b81602086016020860161390f565b601f01601f19169290920160200192915050565b6040815260006139726040830185613933565b82810360208401526139848185613933565b95945050505050565b600080604083850312156139a057600080fd5b6139a983613653565b946020939093013593505050565b6020815260006117f46020830184613933565b6000806000606084860312156139df57600080fd5b6139e884613653565b92506139f660208501613653565b9150604084013560028110613a0a57600080fd5b809150509250925092565b60008060008060808587031215613a2b57600080fd5b613a3485613653565b9350613a4260208601613653565b925060408501359150613a5760608601613653565b905092959194509250565b634e487b7160e01b600052602160045260246000fd5b6020810160028310613a9a57634e487b7160e01b600052602160045260246000fd5b91905290565b80151581146117b557600080fd5b600060208284031215613ac057600080fd5b81356117f481613aa0565b600080600060408486031215613ae057600080fd5b613ae984613653565b925060208401356001600160401b03811115613b0457600080fd5b613b108682870161370a565b9497909650939450505050565b6020808252825182820181905260009190848201906040850190845b818110156136fe57835183529284019291840191600101613b39565b60008060008060008060808789031215613b6e57600080fd5b613b7787613653565b955060208701356001600160401b0380821115613b9357600080fd5b613b9f8a838b0161370a565b90975095506040890135915080821115613bb857600080fd5b50613bc589828a0161370a565b9094509250613bd8905060608801613653565b90509295509295509295565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215613c0d57600080fd5b613c1683613653565b915060208301356001600160401b0380821115613c3257600080fd5b818501915085601f830112613c4657600080fd5b813581811115613c5857613c58613be4565b604051601f8201601f19908116603f01168101908382118183101715613c8057613c80613be4565b81604052828152886020848701011115613c9957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613d1257603f19888603018452613d00858351613933565b94509285019290850190600101613ce4565b5092979650505050505050565b60008060008060008060a08789031215613d3857600080fd5b86356001600160401b03811115613d4e57600080fd5b613d5a89828a016137ce565b90975095505060208701359350613d7360408801613653565b9250613d8160608801613653565b9150608087013590509295509295509295565b60008060008060008060008060a0898b031215613db057600080fd5b88356001600160401b0380821115613dc757600080fd5b613dd38c838d016137ce565b909a50985060208b01359750889150613dee60408c01613653565b965060608b0135915080821115613e0457600080fd5b613e108c838d0161370a565b909650945060808b0135915080821115613e2957600080fd5b50613e368b828c0161370a565b999c989b5096995094979396929594505050565b60008060408385031215613e5d57600080fd5b613e6683613653565b91506020830135613e7681613aa0565b809150509250929050565b60208082526013908201527210531317d0d3105253525391d7d4105554d151606a1b604082015260600190565b60208082526019908201527f434c41494d494e475f5041555345445f464f525f544f4b454e00000000000000604082015260600190565b602080825260159082015274141554d2115497d393d517d49151d254d511549151605a1b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115610f6a57610f6a613f2a565b634e487b7160e01b600052603160045260246000fd5b8183823760009101908152919050565b600181811c90821680613f8d57607f821691505b602082108103613fad57634e487b7160e01b600052602260045260246000fd5b50919050565b80820180821115610f6a57610f6a613f2a565b601f821115610a58576000816000526020600020601f850160051c81016020861015613fef5750805b601f850160051c820191505b8181101561400e57828155600101613ffb565b505050505050565b600019600383901b1c191660019190911b1790565b6001600160401b0383111561404257614042613be4565b614056836140508354613f79565b83613fc6565b6000601f84116001811461408457600085156140725750838201355b61407c8682614016565b845550610bde565b600083815260209020601f19861690835b828110156140b55786850135825560209485019460019092019101614095565b50868210156140d25760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208082526018908201527f4e4f545f4f4e474f494e475f44495350454e534154494f4e0000000000000000604082015260600190565b600080835461412981613f79565b60018281168015614141576001811461415657614185565b60ff1984168752821515830287019450614185565b8760005260208060002060005b8581101561417c5781548a820152908401908201614163565b50505082870194505b50929695505050505050565b81810361419c575050565b6141a68254613f79565b6001600160401b038111156141bd576141bd613be4565b6141d1816141cb8454613f79565b84613fc6565b6000601f8211600181146141ff57600083156141ed5750848201545b6141f78482614016565b855550610bde565b600085815260209020601f19841690600086815260209020845b838110156142395782860154825560019586019590910190602001614219565b50858310156142575781850154600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006020828403121561427957600080fd5b81516117f481613aa0565b81516001600160401b0381111561429d5761429d613be4565b6142ab816141cb8454613f79565b602080601f8311600181146142da57600084156142c85750858301515b6142d28582614016565b86555061400e565b600085815260208120601f198616915b82811015614309578886015182559484019460019091019084016142ea565b508582101561425757939096015160001960f8600387901b161c19169092555050600190811b01905550565b60006020828403121561434757600080fd5b5051919050565b6000825161436081846020870161390f565b919091019291505056fea2646970667358221220882c27ef62090255e612daffa5cfd82f9b3605233ffeaccb0eec03330736d58b64736f6c63430008180033
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.