More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 3,534 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Compound | 20196325 | 41 mins ago | IN | 0 ETH | 0.00084416 | ||||
Stake | 20195107 | 4 hrs ago | IN | 0 ETH | 0.00014704 | ||||
Claim | 20194728 | 6 hrs ago | IN | 0 ETH | 0.00006923 | ||||
Withdraw | 20194702 | 6 hrs ago | IN | 0 ETH | 0.00017043 | ||||
Stake | 20194386 | 7 hrs ago | IN | 0 ETH | 0.00016322 | ||||
Compound | 20194095 | 8 hrs ago | IN | 0 ETH | 0.00059755 | ||||
Compound | 20193695 | 9 hrs ago | IN | 0 ETH | 0.00039987 | ||||
Stake | 20193485 | 10 hrs ago | IN | 0 ETH | 0.00018644 | ||||
Claim | 20193199 | 11 hrs ago | IN | 0 ETH | 0.00039591 | ||||
Stake | 20192612 | 13 hrs ago | IN | 0 ETH | 0.0003541 | ||||
Claim | 20192516 | 13 hrs ago | IN | 0 ETH | 0.00014936 | ||||
Stake | 20192377 | 13 hrs ago | IN | 0 ETH | 0.0003362 | ||||
Claim | 20191883 | 15 hrs ago | IN | 0 ETH | 0.00063788 | ||||
Compound | 20190903 | 18 hrs ago | IN | 0 ETH | 0.00143471 | ||||
Stake | 20190611 | 19 hrs ago | IN | 0 ETH | 0.00075891 | ||||
Claim | 20190567 | 20 hrs ago | IN | 0 ETH | 0.00031079 | ||||
Claim | 20190437 | 20 hrs ago | IN | 0 ETH | 0.00026971 | ||||
Stake | 20190272 | 20 hrs ago | IN | 0 ETH | 0.00074634 | ||||
Stake | 20190266 | 21 hrs ago | IN | 0 ETH | 0.00061714 | ||||
Stake | 20190247 | 21 hrs ago | IN | 0 ETH | 0.00060189 | ||||
Claim | 20189199 | 24 hrs ago | IN | 0 ETH | 0.00029206 | ||||
Claim | 20187736 | 29 hrs ago | IN | 0 ETH | 0.00012975 | ||||
Withdraw | 20187593 | 29 hrs ago | IN | 0 ETH | 0.00038726 | ||||
Claim | 20186333 | 34 hrs ago | IN | 0 ETH | 0.0002497 | ||||
Stake | 20186059 | 35 hrs ago | IN | 0 ETH | 0.00049717 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
20196325 | 41 mins ago | 0.00763011 ETH | ||||
20194728 | 6 hrs ago | 0.01341045 ETH | ||||
20194702 | 6 hrs ago | 0.00162823 ETH | ||||
20194095 | 8 hrs ago | 0.00934673 ETH | ||||
20193695 | 9 hrs ago | 0.01436635 ETH | ||||
20193199 | 11 hrs ago | 0.00214998 ETH | ||||
20192516 | 13 hrs ago | 0.25781885 ETH | ||||
20191883 | 15 hrs ago | 0.01736041 ETH | ||||
20190903 | 18 hrs ago | 0.01144666 ETH | ||||
20190567 | 20 hrs ago | 0.14609558 ETH | ||||
20190437 | 20 hrs ago | 0.00125033 ETH | ||||
20189199 | 24 hrs ago | 0.00050908 ETH | ||||
20187736 | 29 hrs ago | 0.00178848 ETH | ||||
20186333 | 34 hrs ago | 0.01162221 ETH | ||||
20185417 | 37 hrs ago | 0.00296415 ETH | ||||
20184661 | 39 hrs ago | 0.00447239 ETH | ||||
20184218 | 41 hrs ago | 0.013975 ETH | ||||
20184194 | 41 hrs ago | 0.02059248 ETH | ||||
20183659 | 43 hrs ago | 0.01424898 ETH | ||||
20183619 | 43 hrs ago | 0.02203772 ETH | ||||
20182390 | 47 hrs ago | 0.44266013 ETH | ||||
20177173 | 2 days ago | 0.00263574 ETH | ||||
20177007 | 2 days ago | 0.38548851 ETH | ||||
20174561 | 3 days ago | 0.00670841 ETH | ||||
20174364 | 3 days ago | 0.00428006 ETH |
Loading...
Loading
Contract Name:
OTSeaStaking
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
/* [.... [... [...... [.. .. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [. [.. [.. [.. [.. [.. [.. [.. [..... [..[.. [.. [.. [.. [.. [.. [..[. [.. [.. [.... [.. [.. .. [.... [.. [... OTSea Staking. https://otsea.io https://t.me/OTSeaPortal https://twitter.com/OTSeaERC20 */ // SPDX-License-Identifier: MIT pragma solidity =0.8.20; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; import "contracts/helpers/ListHelper.sol"; import "contracts/helpers/TransferHelper.sol"; import "contracts/libraries/OTSeaErrors.sol"; /** * @title OTSea Staking Contract * @dev This contract enables users to stake tokens and earn rewards from v1 token fees and platform revenue. * It initiates a new epoch with each reward distribution. Users who stake during an epoch do not receive rewards * for that epoch, preventing exploitation through immediate pre-reward staking and withdrawal. * Similarly, users withdrawing their stake in any epoch forfeit rewards that would be distributed at the end of * the epoch. Rewards are calculated pro-rata based on the token amount staked in each epoch. * * If the revenue for distribution is less than 0.0001 ETH or if the total staked tokens are fewer than 1, the current * epoch is skipped. No rewards are distributed in this case, and the accumulated revenue is carried over to the * next epoch. */ contract OTSeaStaking is Ownable, TransferHelper, ListHelper { using SafeERC20 for IERC20; struct Deposit { /** * @dev rewardReferenceEpoch represents the reference point that rewards should be based off of. * - Upon depositing it is set to the currentEpoch + 1. * - Upon claiming rewards it is set to the currentEpoch * - Upon withdrawing it is set to 0 */ uint32 rewardReferenceEpoch; uint88 amount; } struct Epoch { uint168 startedAt; uint88 totalStake; uint256 sharePerToken; } IUniswapV2Router02 private constant _router = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); uint256 private constant REWARD_PRECISION = 10e38; address private immutable _revenueDistributor; bool public isDepositingAllowed; uint32 private _currentEpoch = 1; IERC20 private _otseaERC20; mapping(address => Deposit[]) private _deposits; mapping(uint32 => Epoch) private _epochs; error NoRewards(); error InvalidEpoch(); error DepositNotFound(uint256 index); event Initialized(address token); event ToggledDepositing(bool isDepositingAllowed); event Deposited(address indexed account, uint256 indexed index, Deposit deposit); event Withdrawal( address indexed account, address indexed receiver, uint256[] indexes, uint88 amount ); event Claimed( address indexed account, address indexed receiver, uint256[] indexes, uint256 amount ); event Compounded( address indexed account, uint256[] indexes, uint256 amountSwapped, uint256 indexed newDepositIndex, Deposit deposit ); event EpochEnded(uint32 indexed id, Epoch epoch, uint256 distributed); modifier onlyRevenueDistributor() { _isCallerRevenueDistributor(); _; } /** * @param _multiSigAdmin Multi-sig admin * @param revenueDistributor_ Revenue distributor contract */ constructor(address _multiSigAdmin, address revenueDistributor_) Ownable(_multiSigAdmin) { if (address(revenueDistributor_) == address(0)) revert OTSeaErrors.InvalidAddress(); _revenueDistributor = revenueDistributor_; } /** * @notice Initialize and start the first epoch * @param _token Token */ function initialize(IERC20 _token) external onlyOwner { if (address(_token) == address(0)) revert OTSeaErrors.InvalidAddress(); if (_isInitialized()) revert OTSeaErrors.NotAvailable(); _otseaERC20 = _token; _epochs[1].startedAt = uint168(block.timestamp); emit Initialized(address(_token)); } /// @notice Toggle depositing function toggleDepositing() external onlyOwner { if (!_isInitialized()) revert OTSeaErrors.NotAvailable(); isDepositingAllowed = !isDepositingAllowed; emit ToggledDepositing(isDepositingAllowed); } /// @notice Distribute ETH to stakers (only revenue distributor) function distribute() external payable onlyRevenueDistributor { uint32 currentEpoch = _currentEpoch; uint256 sharePerToken = (REWARD_PRECISION * msg.value) / _epochs[currentEpoch].totalStake; _epochs[currentEpoch].sharePerToken += sharePerToken; _nextEpoch(); emit EpochEnded(currentEpoch, _epochs[currentEpoch], msg.value); } /// @notice Skip epoch (only revenue distributor) function skipEpoch() external onlyRevenueDistributor { uint32 currentEpoch = _currentEpoch; _nextEpoch(); emit EpochEnded(currentEpoch, _epochs[currentEpoch], 0); } /** * @notice Stake OTSea tokens and earn ETH * @param _amount OTSea amount */ function stake(uint88 _amount) external { if (!isDepositingAllowed) revert OTSeaErrors.NotAvailable(); if (_amount == 0) revert OTSeaErrors.InvalidAmount(); _checkSufficientAmount(_amount); /** * @dev current deposit index = _deposits[_msgSender()].length - 1, therefore if we add 1 to get the next index * it cancels out with the "-1" to just give _deposits[_msgSender()].length */ Deposit memory deposit = _createDeposit(_amount); _otseaERC20.safeTransferFrom(_msgSender(), address(this), uint256(_amount)); emit Deposited(_msgSender(), _deposits[_msgSender()].length - 1, deposit); } /** * @notice Withdraw multiple deposits as well as claim their rewards * @param _indexes A list of deposit IDs to withdraw * @param _receiver Address to receive the tokens and ETH */ function withdraw(uint256[] calldata _indexes, address _receiver) external { if (_receiver == address(0)) revert OTSeaErrors.InvalidAddress(); (uint88 totalAmount, uint256 totalRewards) = _withdrawMultiple(_indexes); if (totalRewards != 0) { _transferETHOrRevert(_receiver, totalRewards); emit Claimed(_msgSender(), _receiver, _indexes, totalRewards); } _otseaERC20.safeTransfer(_receiver, uint256(totalAmount)); emit Withdrawal(_msgSender(), _receiver, _indexes, totalAmount); } /** * @notice Claim rewards for multiple deposits * @param _indexes A list of deposit IDs to claim * @param _receiver Address to receive ETH */ function claim(uint256[] calldata _indexes, address _receiver) external { if (_receiver == address(0)) revert OTSeaErrors.InvalidAddress(); uint256 totalRewards = _claimMultiple(_indexes); _transferETHOrRevert(_receiver, totalRewards); emit Claimed(_msgSender(), _receiver, _indexes, totalRewards); } /** * @notice Compound rewards by swapping ETH for tokens and creating a new deposit * @param _indexes A list of deposit IDs to compound * @param _amountToSwap Amount of rewards (ETH) to swap for tokens, left over rewards are sent to _remainderReceiver * @param _minTokenAmount Minimum token amount to receive when swapping _amountToSwap * @param _remainderReceiver Address to receive any remaining rewards (can be the zero address if amountToSwap * is equal to the total rewards for _indexes) * @dev The staking contract is exempt from buy fees making compounding fee-free */ function compound( uint256[] calldata _indexes, uint256 _amountToSwap, uint88 _minTokenAmount, address _remainderReceiver ) external { if (_amountToSwap == 0 || _minTokenAmount == 0) revert OTSeaErrors.InvalidAmount(); uint256 totalRewards = _claimMultiple(_indexes); if (totalRewards < _amountToSwap) revert OTSeaErrors.InvalidAmount(); uint256 remaining = totalRewards - _amountToSwap; if (remaining != 0) { if (_remainderReceiver == address(0)) revert OTSeaErrors.InvalidAddress(); _transferETHOrRevert(_remainderReceiver, remaining); emit Claimed(_msgSender(), _remainderReceiver, _indexes, remaining); } uint88 tokens = _swapETHForTokens(_amountToSwap, _minTokenAmount); Deposit memory deposit = _createDeposit(tokens); emit Compounded( _msgSender(), _indexes, _amountToSwap, _deposits[_msgSender()].length - 1, deposit ); } /** * @notice Get details about an epoch * @param _epoch Epoch ID (must be greater than 0 and not greater than the current epoch + 1) * @return Epoch Epoch details */ function getEpoch(uint32 _epoch) external view returns (Epoch memory) { if (_epoch == 0 || _currentEpoch + 1 < _epoch) revert InvalidEpoch(); return _epochs[_epoch]; } /** * @notice Get the current epoch ID and details * @return uint32 Epoch ID * @return Epoch Epoch details */ function getCurrentEpoch() external view returns (uint32, Epoch memory) { return (_currentEpoch, _epochs[_currentEpoch]); } /** * @notice Get the total deposits by a user * @param _account Account * @return total Total deposits by _account */ function getTotalDeposits(address _account) public view returns (uint256 total) { if (_account == address(0)) revert OTSeaErrors.InvalidAddress(); return _deposits[_account].length; } /** * @notice Get a deposit for a user by index * @param _account Account * @param _index Index of deposit * @return Deposit Deposit belonging to _account at index _index */ function getDeposit(address _account, uint256 _index) external view returns (Deposit memory) { if (getTotalDeposits(_account) <= _index) revert DepositNotFound(_index); return _deposits[_account][_index]; } /** * @notice Get a list of deposits for a user in a sequence from an start index to an end index (inclusive) * @param _account Account * @param _startIndex Start deposit index * @param _endIndex End deposit index * @return deposits A list of deposits for _account within the range of _startIndex and _endIndex (inclusive) */ function getDepositsInSequence( address _account, uint256 _startIndex, uint256 _endIndex ) external view onlyValidSequence(_startIndex, _endIndex, getTotalDeposits(_account), ALLOW_ZERO) returns (Deposit[] memory deposits) { deposits = new Deposit[](_endIndex - _startIndex + 1); uint256 index; uint256 depositIndex = _startIndex; for (depositIndex; depositIndex <= _endIndex; ) { deposits[index] = _deposits[_account][depositIndex]; unchecked { index++; depositIndex++; } } return deposits; } /** * @notice Get a list of deposits for a user by providing a list * @param _account Account * @param _indexes A list of deposit indexes * @return deposits A list of deposits for _account based on the _indexes provided */ function getDepositsByList( address _account, uint256[] calldata _indexes ) external view returns (Deposit[] memory deposits) { uint256 length = _indexes.length; _validateListLength(length); uint256 total = getTotalDeposits(_account); deposits = new Deposit[](length); for (uint256 i; i < length; ) { if (total <= _indexes[i]) revert DepositNotFound(_indexes[i]); deposits[i] = _deposits[_account][_indexes[i]]; unchecked { i++; } } return deposits; } /** * @notice Calculate rewards for a user * @param _account Account * @param _indexes A list of deposit indexes * @return rewards Total rewards for _account based on the _indexes list */ function calculateRewards( address _account, uint256[] calldata _indexes ) external view returns (uint256 rewards) { uint256 length = _indexes.length; _validateListLength(length); uint256 total = getTotalDeposits(_account); for (uint256 i; i < length; ) { if (total <= _indexes[i]) revert DepositNotFound(_indexes[i]); rewards += _calculateRewards(_account, _indexes[i]); unchecked { i++; } } return rewards; } function _nextEpoch() private { /// @dev sets the current epoch = the current while updating state to the next one uint32 nextEpoch = ++_currentEpoch; _epochs[nextEpoch].startedAt = uint88(block.timestamp); _epochs[nextEpoch].sharePerToken = _epochs[nextEpoch - 1].sharePerToken; _epochs[nextEpoch].totalStake += _epochs[nextEpoch - 1].totalStake; } /** * @param _amount Amount to deposit * @return deposit Deposit details */ function _createDeposit(uint88 _amount) private returns (Deposit memory deposit) { uint32 nextEpoch = _currentEpoch + 1; deposit = Deposit(nextEpoch, _amount); _deposits[_msgSender()].push(deposit); _epochs[nextEpoch].totalStake += _amount; return deposit; } /** * @param _indexes A list of deposit indexes * @return totalAmount Total amount to withdraw based on _indexes * @return totalRewards Total amount of rewards based on _indexes */ function _withdrawMultiple( uint256[] calldata _indexes ) private returns (uint88 totalAmount, uint256 totalRewards) { uint256 length = _indexes.length; _validateListLength(length); uint256 total = getTotalDeposits(_msgSender()); uint32 currentEpoch = _currentEpoch; for (uint256 i; i < length; ) { if (total <= _indexes[i]) revert DepositNotFound(_indexes[i]); totalRewards += _calculateRewards(_msgSender(), _indexes[i]); Deposit memory deposit = _deposits[_msgSender()][_indexes[i]]; if (deposit.rewardReferenceEpoch == 0) revert OTSeaErrors.NotAvailable(); _deposits[_msgSender()][_indexes[i]].rewardReferenceEpoch = 0; /** * @dev if the rewardReferenceEpoch is in the future, it means that the user deposited in the current * epoch (currentEpoch). Therefore next epoch's total stake needs to be reduced by the user's deposit. * * If the rewardReferenceEpoch is less than or equal to the currentEpoch it means that the user * either deposited or claimed rewards in a past epoch. Either way it means that the user's * deposit cannot possible be in the future therefore the current epoch's total stake needs to be reduced */ _epochs[ currentEpoch < deposit.rewardReferenceEpoch ? deposit.rewardReferenceEpoch : currentEpoch ].totalStake -= deposit.amount; totalAmount += deposit.amount; unchecked { i++; } } return (totalAmount, totalRewards); } /** * @param _indexes A list of deposit indexes * @return totalRewards Total amount of rewards based on _indexes */ function _claimMultiple(uint256[] calldata _indexes) private returns (uint256 totalRewards) { uint256 length = _indexes.length; _validateListLength(length); uint256 total = getTotalDeposits(_msgSender()); uint32 currentEpoch = _currentEpoch; for (uint256 i; i < length; ) { if (total <= _indexes[i]) revert DepositNotFound(_indexes[i]); totalRewards += _calculateRewards(_msgSender(), _indexes[i]); _deposits[_msgSender()][_indexes[i]].rewardReferenceEpoch = currentEpoch; unchecked { i++; } } if (totalRewards == 0) revert NoRewards(); return totalRewards; } /** * @param _amountToSwap Amount of ETH to swap for tokens * @param _minTokenAmount Minimum token amount to receive when swapping _amountToSwap * @return uint88 Tokens received */ function _swapETHForTokens( uint256 _amountToSwap, uint88 _minTokenAmount ) private returns (uint88) { address[] memory path = new address[](2); path[0] = _router.WETH(); path[1] = address(_otseaERC20); uint256[] memory amounts = _router.swapExactETHForTokens{value: _amountToSwap}( uint256(_minTokenAmount), path, address(this), block.timestamp ); return uint88(amounts[1]); } /** * @param _account Account * @param _index Deposit index belonging to _account * @return uint256 Rewards accumulated by _account for deposit _index */ function _calculateRewards(address _account, uint256 _index) private view returns (uint256) { uint32 rewardReferenceEpoch = _deposits[_account][_index].rewardReferenceEpoch; if (rewardReferenceEpoch == 0 || _currentEpoch <= rewardReferenceEpoch) { return 0; } return (_deposits[_account][_index].amount * (_epochs[_currentEpoch - 1].sharePerToken - _epochs[rewardReferenceEpoch - 1].sharePerToken)) / REWARD_PRECISION; } /// @param _amount Amount function _checkSufficientAmount(uint88 _amount) private view { if (_otseaERC20.balanceOf(_msgSender()) < _amount) revert IERC20Errors.ERC20InsufficientBalance( _msgSender(), _otseaERC20.balanceOf(_msgSender()), uint256(_amount) ); if (_otseaERC20.allowance(_msgSender(), address(this)) < _amount) revert IERC20Errors.ERC20InsufficientAllowance( address(this), _otseaERC20.allowance(_msgSender(), address(this)), uint256(_amount) ); } /// @return bool true if initialized, false if not function _isInitialized() private view returns (bool) { return address(_otseaERC20) != address(0); } function _isCallerRevenueDistributor() private view { if (_msgSender() != _revenueDistributor) revert OTSeaErrors.Unauthorized(); } }
// 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) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// 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; } }
pragma solidity >=0.6.2; interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityETH( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityETHWithPermit( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); }
pragma solidity >=0.6.2; import './IUniswapV2Router01.sol'; interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, address to, uint deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; }
/* [.... [... [...... [.. .. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [. [.. [.. [.. [.. [.. [.. [.. [..... [..[.. [.. [.. [.. [.. [.. [..[. [.. [.. [.... [.. [.. .. [.... [.. [... https://otsea.io https://t.me/OTSeaPortal https://twitter.com/OTSeaERC20 */ // SPDX-License-Identifier: MIT pragma solidity =0.8.20; import "contracts/libraries/OTSeaErrors.sol"; /// @title A list helper contract abstract contract ListHelper { uint16 internal constant LOOP_LIMIT = 500; bool internal constant ALLOW_ZERO = true; bool internal constant DISALLOW_ZERO = false; error InvalidStart(); error InvalidEnd(); error InvalidSequence(); /** * @param _start Start * @param _end End * @param _total List total * @param _allowZero true - zero is a valid start or end, false - zero is an invalid start or end */ modifier onlyValidSequence( uint256 _start, uint256 _end, uint256 _total, bool _allowZero ) { _checkSequence(_start, _end, _total, _allowZero); _; } /** * @param _start Start * @param _end End * @param _total Total * @param _allowZero true - zero is a valid start or end, false - zero is an invalid start or end * @dev check that a range of indexes is valid. */ function _checkSequence( uint256 _start, uint256 _end, uint256 _total, bool _allowZero ) private pure { if (_allowZero) { if (_start >= _total) revert InvalidStart(); if (_end >= _total) revert InvalidEnd(); } else { if (_start == 0 || _start > _total) revert InvalidStart(); if (_end == 0 || _end > _total) revert InvalidEnd(); } if (_start > _end) revert InvalidStart(); if (_end - _start + 1 > LOOP_LIMIT) revert InvalidSequence(); } /// @dev _length List length function _validateListLength(uint256 _length) internal pure { if (_length == 0 || LOOP_LIMIT < _length) revert OTSeaErrors.InvalidArrayLength(); } }
/* [.... [... [...... [.. .. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [. [.. [.. [.. [.. [.. [.. [.. [..... [..[.. [.. [.. [.. [.. [.. [..[. [.. [.. [.... [.. [.. .. [.... [.. [... https://otsea.io https://t.me/OTSeaPortal https://twitter.com/OTSeaERC20 */ // SPDX-License-Identifier: MIT pragma solidity =0.8.20; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/Context.sol"; import "contracts/libraries/OTSeaErrors.sol"; /// @title A transfer helper contract for ETH and tokens contract TransferHelper is Context { using SafeERC20 for IERC20; /// @dev account -> Amount of ETH that failed to transfer mapping(address => uint256) private _maroonedETH; error NativeTransferFailed(); event MaroonedETH(address account, uint256 amount); event MaroonedETHClaimed(address account, address receiver, uint256 amount); /** * @notice Claim marooned ETH * @param _receiver Address to receive the marooned ETH */ function claimMaroonedETH(address _receiver) external { if (_receiver == address(0)) revert OTSeaErrors.InvalidAddress(); uint256 amount = _maroonedETH[_msgSender()]; if (amount == 0) revert OTSeaErrors.NotAvailable(); _maroonedETH[_msgSender()] = 0; _transferETHOrRevert(_receiver, amount); emit MaroonedETHClaimed(_msgSender(), _receiver, amount); } /** * @notice Get the amount of marooned ETH for an account * @param _account Account to check * @return uint256 Marooned ETH */ function getMaroonedETH(address _account) external view returns (uint256) { if (_account == address(0)) revert OTSeaErrors.InvalidAddress(); return _maroonedETH[_account]; } /** * @param _account Account to transfer ETH to * @param _amount Amount of ETH to transfer to _account * @dev Rather than reverting if the transfer fails, the _amount is stored for the _account to later claim */ function _safeETHTransfer(address _account, uint256 _amount) internal { (bool success, ) = _account.call{value: _amount}(""); if (!success) { _maroonedETH[_account] += _amount; emit MaroonedETH(_account, _amount); } } /** * @param _account Account to transfer ETH to * @param _amount Amount of ETH to transfer to _account * @dev The following will revert if the transfer fails */ function _transferETHOrRevert(address _account, uint256 _amount) internal { (bool success, ) = _account.call{value: _amount}(""); if (!success) revert NativeTransferFailed(); } /** * @param _token Token to transfer into the contract from msg.sender * @param _amount Amount of _token to transfer * @return uint256 Actual amount transferred into the contract * @dev This function exists due to _token potentially having taxes */ function _transferInTokens(IERC20 _token, uint256 _amount) internal returns (uint256) { uint256 balanceBefore = _token.balanceOf(address(this)); _token.safeTransferFrom(_msgSender(), address(this), _amount); return _token.balanceOf(address(this)) - balanceBefore; } }
/* [.... [... [...... [.. .. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [.. [. [.. [.. [.. [.. [.. [.. [.. [..... [..[.. [.. [.. [.. [.. [.. [..[. [.. [.. [.... [.. [.. .. [.... [.. [... https://otsea.io https://t.me/OTSeaPortal https://twitter.com/OTSeaERC20 */ // SPDX-License-Identifier: MIT pragma solidity =0.8.20; /// @title Common OTSea errors library OTSeaErrors { error InvalidAmount(); error InvalidAddress(); error InvalidIndex(uint256 index); error InvalidAmountAtIndex(uint256 index); error InvalidAddressAtIndex(uint256 index); error DuplicateAddressAtIndex(uint256 index); error AddressNotFoundAtIndex(uint256 index); error Unauthorized(); error ExpectationMismatch(); error InvalidArrayLength(); error InvalidFee(); error NotAvailable(); error InvalidPurchase(); error InvalidETH(uint256 expected); error Unchanged(); }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_multiSigAdmin","type":"address"},{"internalType":"address","name":"revenueDistributor_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"DepositNotFound","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidArrayLength","type":"error"},{"inputs":[],"name":"InvalidEnd","type":"error"},{"inputs":[],"name":"InvalidEpoch","type":"error"},{"inputs":[],"name":"InvalidSequence","type":"error"},{"inputs":[],"name":"InvalidStart","type":"error"},{"inputs":[],"name":"NativeTransferFailed","type":"error"},{"inputs":[],"name":"NoRewards","type":"error"},{"inputs":[],"name":"NotAvailable","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"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"indexes","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"indexes","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"amountSwapped","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newDepositIndex","type":"uint256"},{"components":[{"internalType":"uint32","name":"rewardReferenceEpoch","type":"uint32"},{"internalType":"uint88","name":"amount","type":"uint88"}],"indexed":false,"internalType":"struct OTSeaStaking.Deposit","name":"deposit","type":"tuple"}],"name":"Compounded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"components":[{"internalType":"uint32","name":"rewardReferenceEpoch","type":"uint32"},{"internalType":"uint88","name":"amount","type":"uint88"}],"indexed":false,"internalType":"struct OTSeaStaking.Deposit","name":"deposit","type":"tuple"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"id","type":"uint32"},{"components":[{"internalType":"uint168","name":"startedAt","type":"uint168"},{"internalType":"uint88","name":"totalStake","type":"uint88"},{"internalType":"uint256","name":"sharePerToken","type":"uint256"}],"indexed":false,"internalType":"struct OTSeaStaking.Epoch","name":"epoch","type":"tuple"},{"indexed":false,"internalType":"uint256","name":"distributed","type":"uint256"}],"name":"EpochEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MaroonedETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MaroonedETHClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isDepositingAllowed","type":"bool"}],"name":"ToggledDepositing","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"indexes","type":"uint256[]"},{"indexed":false,"internalType":"uint88","name":"amount","type":"uint88"}],"name":"Withdrawal","type":"event"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256[]","name":"_indexes","type":"uint256[]"}],"name":"calculateRewards","outputs":[{"internalType":"uint256","name":"rewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_indexes","type":"uint256[]"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"claimMaroonedETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_indexes","type":"uint256[]"},{"internalType":"uint256","name":"_amountToSwap","type":"uint256"},{"internalType":"uint88","name":"_minTokenAmount","type":"uint88"},{"internalType":"address","name":"_remainderReceiver","type":"address"}],"name":"compound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"distribute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getCurrentEpoch","outputs":[{"internalType":"uint32","name":"","type":"uint32"},{"components":[{"internalType":"uint168","name":"startedAt","type":"uint168"},{"internalType":"uint88","name":"totalStake","type":"uint88"},{"internalType":"uint256","name":"sharePerToken","type":"uint256"}],"internalType":"struct OTSeaStaking.Epoch","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getDeposit","outputs":[{"components":[{"internalType":"uint32","name":"rewardReferenceEpoch","type":"uint32"},{"internalType":"uint88","name":"amount","type":"uint88"}],"internalType":"struct OTSeaStaking.Deposit","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256[]","name":"_indexes","type":"uint256[]"}],"name":"getDepositsByList","outputs":[{"components":[{"internalType":"uint32","name":"rewardReferenceEpoch","type":"uint32"},{"internalType":"uint88","name":"amount","type":"uint88"}],"internalType":"struct OTSeaStaking.Deposit[]","name":"deposits","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_startIndex","type":"uint256"},{"internalType":"uint256","name":"_endIndex","type":"uint256"}],"name":"getDepositsInSequence","outputs":[{"components":[{"internalType":"uint32","name":"rewardReferenceEpoch","type":"uint32"},{"internalType":"uint88","name":"amount","type":"uint88"}],"internalType":"struct OTSeaStaking.Deposit[]","name":"deposits","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_epoch","type":"uint32"}],"name":"getEpoch","outputs":[{"components":[{"internalType":"uint168","name":"startedAt","type":"uint168"},{"internalType":"uint88","name":"totalStake","type":"uint88"},{"internalType":"uint256","name":"sharePerToken","type":"uint256"}],"internalType":"struct OTSeaStaking.Epoch","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getMaroonedETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"getTotalDeposits","outputs":[{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isDepositingAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"skipEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint88","name":"_amount","type":"uint88"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleDepositing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_indexes","type":"uint256[]"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040526002805464ffffffff0019166101001790553480156200002357600080fd5b5060405162002a6038038062002a6083398101604081905262000046916200012a565b816001600160a01b0381166200007657604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b6200008181620000bd565b506001600160a01b038116620000aa5760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b03166080525062000162565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200012557600080fd5b919050565b600080604083850312156200013e57600080fd5b62000149836200010d565b915062000159602084016200010d565b90509250929050565b6080516128e26200017e60003960006118da01526128e26000f3fe60806040526004361061012a5760003560e01c8063715018a6116100ab578063b8f4bd7b1161006f578063b8f4bd7b1461033c578063b97dd9e21461035c578063c4d66de8146103e2578063e4fc6b6d14610402578063e97f42ec1461040a578063f2fde38b1461042a57600080fd5b8063715018a61461029f5780638c574b48146102b45780638da5cb5b146102d4578063ab191357146102fc578063b3ae22361461031c57600080fd5b80632726b506116100f25780632726b506146101fe5780633b45fc8d1461022b578063549c1db5146102405780635d40ef3b14610255578063600e26981461027f57600080fd5b8063019f49391461012f5780630251cfa114610151578063068c526f146101845780630d28df48146101a457806313e43aac146101d1575b600080fd5b34801561013b57600080fd5b5061014f61014a366004612214565b61044a565b005b34801561015d57600080fd5b5061017161016c366004612286565b6105ca565b6040519081526020015b60405180910390f35b34801561019057600080fd5b5061017161019f3660046122a3565b61060f565b3480156101b057600080fd5b506101c46101bf3660046122f8565b6106d1565b60405161017b919061231e565b3480156101dd57600080fd5b506101f16101ec366004612351565b610794565b60405161017b9190612386565b34801561020a57600080fd5b5061021e6102193660046123ec565b6108ca565b60405161017b9190612418565b34801561023757600080fd5b5061014f610975565b34801561024c57600080fd5b5061014f610a09565b34801561026157600080fd5b5060025461026f9060ff1681565b604051901515815260200161017b565b34801561028b57600080fd5b5061014f61029a366004612286565b610a96565b3480156102ab57600080fd5b5061014f610b54565b3480156102c057600080fd5b5061014f6102cf36600461243e565b610b68565b3480156102e057600080fd5b506000546040516001600160a01b03909116815260200161017b565b34801561030857600080fd5b5061014f610317366004612495565b610bfc565b34801561032857600080fd5b506101f16103373660046122a3565b610ce8565b34801561034857600080fd5b5061014f61035736600461243e565b610e3f565b34801561036857600080fd5b50604080516060808201835260008083526020808401829052928401819052600254610100900463ffffffff1680825260048452908490208451928301855280546001600160a81b0381168452600160a81b90046001600160581b03169383019390935260019092015481840152915161017b92906124b0565b3480156103ee57600080fd5b5061014f6103fd366004612286565b610f56565b61014f611064565b34801561041657600080fd5b50610171610425366004612286565b611172565b34801561043657600080fd5b5061014f610445366004612286565b6111b7565b82158061045e57506001600160581b038216155b1561047c5760405163162908e360e11b815260040160405180910390fd5b600061048886866111f5565b9050838110156104ab5760405163162908e360e11b815260040160405180910390fd5b60006104b78583612506565b90508015610540576001600160a01b0383166104e65760405163e6c4247b60e01b815260040160405180910390fd5b6104f0838261130c565b6001600160a01b038316336001600160a01b03167ffc85082516ca8fe95d78404d69723bc9f7f40661fbf2ea20dbdb14c2413d5ea68989856040516105379392919061254b565b60405180910390a35b600061054c8686611385565b905060006105598261153e565b3360009081526003602052604090205490915061057890600190612506565b336001600160a01b03167fb36b0bca78508102b324ebe5db2a88a859422647746e43829d0ed9b2ea4403c08b8b8b866040516105b7949392919061256f565b60405180910390a3505050505050505050565b60006001600160a01b0382166105f35760405163e6c4247b60e01b815260040160405180910390fd5b506001600160a01b031660009081526003602052604090205490565b60008161061b81611654565b6000610626866105ca565b905060005b828110156106c657858582818110610645576106456125b4565b90506020020135821161069057858582818110610664576106646125b4565b90506020020135604051631585bdab60e31b815260040161068791815260200190565b60405180910390fd5b6106b2878787848181106106a6576106a66125b4565b90506020020135611680565b6106bc90856125ca565b935060010161062b565b5050505b9392505050565b604080516060810182526000808252602082018190529181019190915263ffffffff82161580610722575060025463ffffffff8084169161071a916101009091041660016125dd565b63ffffffff16105b156107405760405163d5b25b6360e01b815260040160405180910390fd5b5063ffffffff16600090815260046020908152604091829020825160608101845281546001600160a81b0381168252600160a81b90046001600160581b031692810192909252600101549181019190915290565b606082826107a1866105ca565b60016107af848484846117da565b6107b98787612506565b6107c49060016125ca565b67ffffffffffffffff8111156107dc576107dc612601565b60405190808252806020026020018201604052801561082157816020015b60408051808201909152600080825260208201528152602001906001900390816107fa5790505b5094506000875b8781116108bd576001600160a01b038a166000908152600360205260409020805482908110610859576108596125b4565b60009182526020918290206040805180820190915291015463ffffffff8116825264010000000090046001600160581b03169181019190915287518890849081106108a6576108a66125b4565b602090810291909101015260019182019101610828565b5050505050509392505050565b6040805180820190915260008082526020820152816108e8846105ca565b1161090957604051631585bdab60e31b815260048101839052602401610687565b6001600160a01b0383166000908152600360205260409020805483908110610933576109336125b4565b60009182526020918290206040805180820190915291015463ffffffff8116825264010000000090046001600160581b03169181019190915290505b92915050565b61097d6118d7565b600254610100900463ffffffff1661099361191f565b63ffffffff811660008181526004602052604080822090517f07c9d3a8bea400ee1980880fb7f4e3532e56612ff7e6c67e7096e1b3c20818ff926109fe929182546001600160a81b038116825260a81c60208201526001909201546040830152606082015260800190565b60405180910390a250565b610a11611a62565b610a2c600254600160281b90046001600160a01b0316151590565b610a495760405163d9b9141960e01b815260040160405180910390fd5b6002805460ff8082161560ff1990921682179092556040519116151581527fcf98b5903f56681ec310ba2c77f80046c0ed90205c2c9e9f7cf2e2b54dc3c4419060200160405180910390a1565b6001600160a01b038116610abd5760405163e6c4247b60e01b815260040160405180910390fd5b3360009081526001602052604081205490819003610aee5760405163d9b9141960e01b815260040160405180910390fd5b33600090815260016020526040812055610b08828261130c565b604080513381526001600160a01b038416602082015280820183905290517f60e82ffc0c9ca018da948ff9a0e7d95b104367e847eae1ec57d7c9997380ce7f9181900360600190a15050565b610b5c611a62565b610b666000611a8f565b565b6001600160a01b038116610b8f5760405163e6c4247b60e01b815260040160405180910390fd5b6000610b9b84846111f5565b9050610ba7828261130c565b6001600160a01b038216336001600160a01b03167ffc85082516ca8fe95d78404d69723bc9f7f40661fbf2ea20dbdb14c2413d5ea6868685604051610bee9392919061254b565b60405180910390a350505050565b60025460ff16610c1f5760405163d9b9141960e01b815260040160405180910390fd5b806001600160581b0316600003610c495760405163162908e360e11b815260040160405180910390fd5b610c5281611adf565b6000610c5d8261153e565b9050610c8733600254600160281b90046001600160a01b031690306001600160581b038616611d86565b33600090815260036020526040902054610ca390600190612506565b336001600160a01b03167f67dfb2bd87d8afa1e2cf4efc2037c61e5991810ed043680f54f54736a3da85aa83604051610cdc9190612418565b60405180910390a35050565b606081610cf481611654565b6000610cff866105ca565b90508167ffffffffffffffff811115610d1a57610d1a612601565b604051908082528060200260200182016040528015610d5f57816020015b6040805180820190915260008082526020820152815260200190600190039081610d385790505b50925060005b828110156106c657858582818110610d7f57610d7f6125b4565b905060200201358211610d9e57858582818110610664576106646125b4565b6001600160a01b0387166000908152600360205260409020868683818110610dc857610dc86125b4565b9050602002013581548110610ddf57610ddf6125b4565b60009182526020918290206040805180820190915291015463ffffffff8116825264010000000090046001600160581b0316918101919091528451859083908110610e2c57610e2c6125b4565b6020908102919091010152600101610d65565b6001600160a01b038116610e665760405163e6c4247b60e01b815260040160405180910390fd5b600080610e738585611ded565b9150915080600014610ed957610e89838261130c565b6001600160a01b038316336001600160a01b03167ffc85082516ca8fe95d78404d69723bc9f7f40661fbf2ea20dbdb14c2413d5ea6878785604051610ed09392919061254b565b60405180910390a35b600254610f0090600160281b90046001600160a01b0316846001600160581b038516612003565b6001600160a01b038316336001600160a01b03167f54ebfb5e1ba02edcdc895d6b0a7238fb8a3f5798ee21012225cb6d5b80d8c2a7878786604051610f4793929190612617565b60405180910390a35050505050565b610f5e611a62565b6001600160a01b038116610f855760405163e6c4247b60e01b815260040160405180910390fd5b610fa0600254600160281b90046001600160a01b0316151590565b15610fbe5760405163d9b9141960e01b815260040160405180910390fd5b6002805465010000000000600160c81b031916600160281b6001600160a01b038416908102919091179091556001600052600460209081527fabd6e7cb50984ff9c2f3e18a2660c3353dadf4e3291deeb275dae2cd1e44fe0580546001600160a81b031916426001600160a81b03161790556040519182527f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6910160405180910390a150565b61106c6118d7565b600254610100900463ffffffff16600081815260046020526040812054600160a81b90046001600160581b03166110b4347002f050fe938943acc45f65568000000000612644565b6110be919061265b565b63ffffffff83166000908152600460205260408120600101805492935083929091906110eb9084906125ca565b909155506110f9905061191f565b63ffffffff82166000818152600460205260409081902090517f07c9d3a8bea400ee1980880fb7f4e3532e56612ff7e6c67e7096e1b3c20818ff9161116691349082546001600160a81b038116825260a81c60208201526001909201546040830152606082015260800190565b60405180910390a25050565b60006001600160a01b03821661119b5760405163e6c4247b60e01b815260040160405180910390fd5b506001600160a01b031660009081526001602052604090205490565b6111bf611a62565b6001600160a01b0381166111e957604051631e4fbdf760e01b815260006004820152602401610687565b6111f281611a8f565b50565b60008161120181611654565b600061120c336105ca565b600254909150610100900463ffffffff1660005b838110156112e15786868281811061123a5761123a6125b4565b90506020020135831161125957868682818110610664576106646125b4565b61126f338888848181106106a6576106a66125b4565b61127990866125ca565b336000908152600360205260409020909550829088888481811061129f5761129f6125b4565b90506020020135815481106112b6576112b66125b4565b6000918252602090912001805463ffffffff191663ffffffff92909216919091179055600101611220565b508360000361130357604051630fec21fd60e21b815260040160405180910390fd5b50505092915050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611359576040519150601f19603f3d011682016040523d82523d6000602084013e61135e565b606091505b505090508061138057604051633d2cec6f60e21b815260040160405180910390fd5b505050565b60408051600280825260608201835260009283929190602083019080368337019050509050737a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611420919061267d565b81600081518110611433576114336125b4565b6001600160a01b0392831660209182029290920101526002548251600160281b909104909116908290600190811061146d5761146d6125b4565b6001600160a01b0390921660209283029190910190910152604051637ff36ab560e01b8152600090737a250d5630b4cf539739df2c5dacb4c659f2488d90637ff36ab59087906114d0906001600160581b0389169087903090429060040161269a565b60006040518083038185885af11580156114ee573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526115179190810190612704565b90508060018151811061152c5761152c6125b4565b60200260200101519250505092915050565b604080518082019091526000808252602082015260025460009061156e90610100900463ffffffff1660016125dd565b6040805180820190915263ffffffff821681526001600160581b03851660208201529250905060036000336001600160a01b03168152602080820192909252604090810160009081208054600181018255908252838220865191018054878601516001600160581b03908116640100000000026effffffffffffffffffffffffffffff1990921663ffffffff948516179190911790915590851682526004909352208054859260159161162a918591600160a81b9004166127c2565b92506101000a8154816001600160581b0302191690836001600160581b0316021790555050919050565b80158061166257506101f481115b156111f257604051634ec4810560e11b815260040160405180910390fd5b6001600160a01b03821660009081526003602052604081208054829190849081106116ad576116ad6125b4565b60009182526020909120015463ffffffff1690508015806116de575060025463ffffffff8083166101009092041611155b156116ed57600091505061096f565b7002f050fe938943acc45f655680000000006004600061170e6001856127e2565b63ffffffff1663ffffffff16815260200190815260200160002060010154600460006001600260019054906101000a900463ffffffff1661174f91906127e2565b63ffffffff1663ffffffff168152602001908152602001600020600101546117779190612506565b6001600160a01b03861660009081526003602052604090208054869081106117a1576117a16125b4565b6000918252602090912001546117c8919064010000000090046001600160581b0316612644565b6117d2919061265b565b949350505050565b80156118255781841061180057604051630e0d5b9360e21b815260040160405180910390fd5b81831061182057604051631a38ee6360e21b815260040160405180910390fd5b611879565b83158061183157508184115b1561184f57604051630e0d5b9360e21b815260040160405180910390fd5b82158061185b57508183115b1561187957604051631a38ee6360e21b815260040160405180910390fd5b8284111561189a57604051630e0d5b9360e21b815260040160405180910390fd5b6101f46118a78585612506565b6118b29060016125ca565b11156118d1576040516328e2aa3760e01b815260040160405180910390fd5b50505050565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610b66576040516282b42960e81b815260040160405180910390fd5b60006002600181819054906101000a900463ffffffff1661193f906127ff565b825463ffffffff8083166101009490940a848102910219909116179092556000908152600460208190526040822080546001600160a81b0319166001600160581b0342161790559192506119946001846127e2565b63ffffffff1663ffffffff16815260200190815260200160002060010154600460008363ffffffff1663ffffffff16815260200190815260200160002060010181905550600460006001836119e991906127e2565b63ffffffff9081168252602080830193909352604091820160009081205491851681526004909352912080546001600160581b03600160a81b93849004811693601592611a3b928692909104166127c2565b92506101000a8154816001600160581b0302191690836001600160581b0316021790555050565b6000546001600160a01b03163314610b665760405163118cdaa760e01b8152336004820152602401610687565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6002546001600160581b03821690600160281b90046001600160a01b03166370a08231336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611b47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6b9190612822565b1015611c2c5733600254600160281b90046001600160a01b03166370a08231336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611bcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf39190612822565b60405163391434e360e21b81526001600160a01b03909216600483015260248201526001600160581b0382166044820152606401610687565b6002546001600160581b03821690600160281b90046001600160a01b031663dd62ed3e336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604401602060405180830381865afa158015611c9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cbe9190612822565b10156111f2576002543090600160281b90046001600160a01b031663dd62ed3e336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604401602060405180830381865afa158015611d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d4d9190612822565b604051637dc7a0d960e11b81526001600160a01b03909216600483015260248201526001600160581b0382166044820152606401610687565b6040516001600160a01b0384811660248301528381166044830152606482018390526118d19186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612034565b60008082611dfa81611654565b6000611e05336105ca565b600254909150610100900463ffffffff1660005b83811015611ff757878782818110611e3357611e336125b4565b905060200201358311611e5257878782818110610664576106646125b4565b611e68338989848181106106a6576106a66125b4565b611e7290866125ca565b33600090815260036020526040812091965090898984818110611e9757611e976125b4565b9050602002013581548110611eae57611eae6125b4565b600091825260208083206040805180820190915292015463ffffffff81168084526401000000009091046001600160581b0316918301919091529092509003611f0a5760405163d9b9141960e01b815260040160405180910390fd5b3360009081526003602052604081208a8a85818110611f2b57611f2b6125b4565b9050602002013581548110611f4257611f426125b4565b6000918252602080832091909101805463ffffffff191663ffffffff9485161790558301518351909260049291811690871610611f7f5785611f82565b83515b63ffffffff16815260208101919091526040016000208054601590611fb8908490600160a81b90046001600160581b031661283b565b92506101000a8154816001600160581b0302191690836001600160581b03160217905550806020015187611fec91906127c2565b965050600101611e19565b505050505b9250929050565b6040516001600160a01b0383811660248301526044820183905261138091859182169063a9059cbb90606401611dbb565b60006120496001600160a01b03841683612097565b9050805160001415801561206e57508080602001905181019061206c919061285b565b155b1561138057604051635274afe760e01b81526001600160a01b0384166004820152602401610687565b60606106ca8383600084600080856001600160a01b031684866040516120bd919061287d565b60006040518083038185875af1925050503d80600081146120fa576040519150601f19603f3d011682016040523d82523d6000602084013e6120ff565b606091505b509150915061210f868383612119565b9695505050505050565b60608261212e5761212982612175565b6106ca565b815115801561214557506001600160a01b0384163b155b1561216e57604051639996b31560e01b81526001600160a01b0385166004820152602401610687565b50806106ca565b8051156121855780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60008083601f8401126121b057600080fd5b50813567ffffffffffffffff8111156121c857600080fd5b6020830191508360208260051b8501011115611ffc57600080fd5b80356001600160581b03811681146121fa57600080fd5b919050565b6001600160a01b03811681146111f257600080fd5b60008060008060006080868803121561222c57600080fd5b853567ffffffffffffffff81111561224357600080fd5b61224f8882890161219e565b90965094505060208601359250612268604087016121e3565b91506060860135612278816121ff565b809150509295509295909350565b60006020828403121561229857600080fd5b81356106ca816121ff565b6000806000604084860312156122b857600080fd5b83356122c3816121ff565b9250602084013567ffffffffffffffff8111156122df57600080fd5b6122eb8682870161219e565b9497909650939450505050565b60006020828403121561230a57600080fd5b813563ffffffff811681146106ca57600080fd5b81516001600160a81b031681526020808301516001600160581b031690820152604080830151908201526060810161096f565b60008060006060848603121561236657600080fd5b8335612371816121ff565b95602085013595506040909401359392505050565b602080825282518282018190526000919060409081850190868401855b828110156123df576123cf848351805163ffffffff1682526020908101516001600160581b0316910152565b92840192908501906001016123a3565b5091979650505050505050565b600080604083850312156123ff57600080fd5b823561240a816121ff565b946020939093013593505050565b815163ffffffff1681526020808301516001600160581b0316908201526040810161096f565b60008060006040848603121561245357600080fd5b833567ffffffffffffffff81111561246a57600080fd5b6124768682870161219e565b909450925050602084013561248a816121ff565b809150509250925092565b6000602082840312156124a757600080fd5b6106ca826121e3565b63ffffffff83168152608081016106ca602083018480516001600160a81b031682526020808201516001600160581b031690830152604090810151910152565b634e487b7160e01b600052601160045260246000fd5b8181038181111561096f5761096f6124f0565b81835260006001600160fb1b0383111561253257600080fd5b8260051b80836020870137939093016020019392505050565b60408152600061255f604083018587612519565b9050826020830152949350505050565b608081526000612583608083018688612519565b6020838101869052845163ffffffff1660408501528401516001600160581b03166060840152905095945050505050565b634e487b7160e01b600052603260045260246000fd5b8082018082111561096f5761096f6124f0565b63ffffffff8181168382160190808211156125fa576125fa6124f0565b5092915050565b634e487b7160e01b600052604160045260246000fd5b60408152600061262b604083018587612519565b90506001600160581b0383166020830152949350505050565b808202811582820484141761096f5761096f6124f0565b60008261267857634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561268f57600080fd5b81516106ca816121ff565b600060808201868352602060808185015281875180845260a086019150828901935060005b818110156126e45784516001600160a01b0316835293830193918301916001016126bf565b50506001600160a01b039690961660408501525050506060015292915050565b6000602080838503121561271757600080fd5b825167ffffffffffffffff8082111561272f57600080fd5b818501915085601f83011261274357600080fd5b81518181111561275557612755612601565b8060051b604051601f19603f8301168101818110858211171561277a5761277a612601565b60405291825284820192508381018501918883111561279857600080fd5b938501935b828510156127b65784518452938501939285019261279d565b98975050505050505050565b6001600160581b038181168382160190808211156125fa576125fa6124f0565b63ffffffff8281168282160390808211156125fa576125fa6124f0565b600063ffffffff808316818103612818576128186124f0565b6001019392505050565b60006020828403121561283457600080fd5b5051919050565b6001600160581b038281168282160390808211156125fa576125fa6124f0565b60006020828403121561286d57600080fd5b815180151581146106ca57600080fd5b6000825160005b8181101561289e5760208186018101518583015201612884565b50600092019182525091905056fea2646970667358221220cac8aa0db0d4c153dc7d9a55b395d376e7c33a0eef119eec1cb3a7ad113fa24464736f6c634300081400330000000000000000000000000adedc7487c59ece60178cf69b8df7e3c4730d9000000000000000000000000034bccf4af03870265fe99cec262524f343cca7ff
Deployed Bytecode
0x60806040526004361061012a5760003560e01c8063715018a6116100ab578063b8f4bd7b1161006f578063b8f4bd7b1461033c578063b97dd9e21461035c578063c4d66de8146103e2578063e4fc6b6d14610402578063e97f42ec1461040a578063f2fde38b1461042a57600080fd5b8063715018a61461029f5780638c574b48146102b45780638da5cb5b146102d4578063ab191357146102fc578063b3ae22361461031c57600080fd5b80632726b506116100f25780632726b506146101fe5780633b45fc8d1461022b578063549c1db5146102405780635d40ef3b14610255578063600e26981461027f57600080fd5b8063019f49391461012f5780630251cfa114610151578063068c526f146101845780630d28df48146101a457806313e43aac146101d1575b600080fd5b34801561013b57600080fd5b5061014f61014a366004612214565b61044a565b005b34801561015d57600080fd5b5061017161016c366004612286565b6105ca565b6040519081526020015b60405180910390f35b34801561019057600080fd5b5061017161019f3660046122a3565b61060f565b3480156101b057600080fd5b506101c46101bf3660046122f8565b6106d1565b60405161017b919061231e565b3480156101dd57600080fd5b506101f16101ec366004612351565b610794565b60405161017b9190612386565b34801561020a57600080fd5b5061021e6102193660046123ec565b6108ca565b60405161017b9190612418565b34801561023757600080fd5b5061014f610975565b34801561024c57600080fd5b5061014f610a09565b34801561026157600080fd5b5060025461026f9060ff1681565b604051901515815260200161017b565b34801561028b57600080fd5b5061014f61029a366004612286565b610a96565b3480156102ab57600080fd5b5061014f610b54565b3480156102c057600080fd5b5061014f6102cf36600461243e565b610b68565b3480156102e057600080fd5b506000546040516001600160a01b03909116815260200161017b565b34801561030857600080fd5b5061014f610317366004612495565b610bfc565b34801561032857600080fd5b506101f16103373660046122a3565b610ce8565b34801561034857600080fd5b5061014f61035736600461243e565b610e3f565b34801561036857600080fd5b50604080516060808201835260008083526020808401829052928401819052600254610100900463ffffffff1680825260048452908490208451928301855280546001600160a81b0381168452600160a81b90046001600160581b03169383019390935260019092015481840152915161017b92906124b0565b3480156103ee57600080fd5b5061014f6103fd366004612286565b610f56565b61014f611064565b34801561041657600080fd5b50610171610425366004612286565b611172565b34801561043657600080fd5b5061014f610445366004612286565b6111b7565b82158061045e57506001600160581b038216155b1561047c5760405163162908e360e11b815260040160405180910390fd5b600061048886866111f5565b9050838110156104ab5760405163162908e360e11b815260040160405180910390fd5b60006104b78583612506565b90508015610540576001600160a01b0383166104e65760405163e6c4247b60e01b815260040160405180910390fd5b6104f0838261130c565b6001600160a01b038316336001600160a01b03167ffc85082516ca8fe95d78404d69723bc9f7f40661fbf2ea20dbdb14c2413d5ea68989856040516105379392919061254b565b60405180910390a35b600061054c8686611385565b905060006105598261153e565b3360009081526003602052604090205490915061057890600190612506565b336001600160a01b03167fb36b0bca78508102b324ebe5db2a88a859422647746e43829d0ed9b2ea4403c08b8b8b866040516105b7949392919061256f565b60405180910390a3505050505050505050565b60006001600160a01b0382166105f35760405163e6c4247b60e01b815260040160405180910390fd5b506001600160a01b031660009081526003602052604090205490565b60008161061b81611654565b6000610626866105ca565b905060005b828110156106c657858582818110610645576106456125b4565b90506020020135821161069057858582818110610664576106646125b4565b90506020020135604051631585bdab60e31b815260040161068791815260200190565b60405180910390fd5b6106b2878787848181106106a6576106a66125b4565b90506020020135611680565b6106bc90856125ca565b935060010161062b565b5050505b9392505050565b604080516060810182526000808252602082018190529181019190915263ffffffff82161580610722575060025463ffffffff8084169161071a916101009091041660016125dd565b63ffffffff16105b156107405760405163d5b25b6360e01b815260040160405180910390fd5b5063ffffffff16600090815260046020908152604091829020825160608101845281546001600160a81b0381168252600160a81b90046001600160581b031692810192909252600101549181019190915290565b606082826107a1866105ca565b60016107af848484846117da565b6107b98787612506565b6107c49060016125ca565b67ffffffffffffffff8111156107dc576107dc612601565b60405190808252806020026020018201604052801561082157816020015b60408051808201909152600080825260208201528152602001906001900390816107fa5790505b5094506000875b8781116108bd576001600160a01b038a166000908152600360205260409020805482908110610859576108596125b4565b60009182526020918290206040805180820190915291015463ffffffff8116825264010000000090046001600160581b03169181019190915287518890849081106108a6576108a66125b4565b602090810291909101015260019182019101610828565b5050505050509392505050565b6040805180820190915260008082526020820152816108e8846105ca565b1161090957604051631585bdab60e31b815260048101839052602401610687565b6001600160a01b0383166000908152600360205260409020805483908110610933576109336125b4565b60009182526020918290206040805180820190915291015463ffffffff8116825264010000000090046001600160581b03169181019190915290505b92915050565b61097d6118d7565b600254610100900463ffffffff1661099361191f565b63ffffffff811660008181526004602052604080822090517f07c9d3a8bea400ee1980880fb7f4e3532e56612ff7e6c67e7096e1b3c20818ff926109fe929182546001600160a81b038116825260a81c60208201526001909201546040830152606082015260800190565b60405180910390a250565b610a11611a62565b610a2c600254600160281b90046001600160a01b0316151590565b610a495760405163d9b9141960e01b815260040160405180910390fd5b6002805460ff8082161560ff1990921682179092556040519116151581527fcf98b5903f56681ec310ba2c77f80046c0ed90205c2c9e9f7cf2e2b54dc3c4419060200160405180910390a1565b6001600160a01b038116610abd5760405163e6c4247b60e01b815260040160405180910390fd5b3360009081526001602052604081205490819003610aee5760405163d9b9141960e01b815260040160405180910390fd5b33600090815260016020526040812055610b08828261130c565b604080513381526001600160a01b038416602082015280820183905290517f60e82ffc0c9ca018da948ff9a0e7d95b104367e847eae1ec57d7c9997380ce7f9181900360600190a15050565b610b5c611a62565b610b666000611a8f565b565b6001600160a01b038116610b8f5760405163e6c4247b60e01b815260040160405180910390fd5b6000610b9b84846111f5565b9050610ba7828261130c565b6001600160a01b038216336001600160a01b03167ffc85082516ca8fe95d78404d69723bc9f7f40661fbf2ea20dbdb14c2413d5ea6868685604051610bee9392919061254b565b60405180910390a350505050565b60025460ff16610c1f5760405163d9b9141960e01b815260040160405180910390fd5b806001600160581b0316600003610c495760405163162908e360e11b815260040160405180910390fd5b610c5281611adf565b6000610c5d8261153e565b9050610c8733600254600160281b90046001600160a01b031690306001600160581b038616611d86565b33600090815260036020526040902054610ca390600190612506565b336001600160a01b03167f67dfb2bd87d8afa1e2cf4efc2037c61e5991810ed043680f54f54736a3da85aa83604051610cdc9190612418565b60405180910390a35050565b606081610cf481611654565b6000610cff866105ca565b90508167ffffffffffffffff811115610d1a57610d1a612601565b604051908082528060200260200182016040528015610d5f57816020015b6040805180820190915260008082526020820152815260200190600190039081610d385790505b50925060005b828110156106c657858582818110610d7f57610d7f6125b4565b905060200201358211610d9e57858582818110610664576106646125b4565b6001600160a01b0387166000908152600360205260409020868683818110610dc857610dc86125b4565b9050602002013581548110610ddf57610ddf6125b4565b60009182526020918290206040805180820190915291015463ffffffff8116825264010000000090046001600160581b0316918101919091528451859083908110610e2c57610e2c6125b4565b6020908102919091010152600101610d65565b6001600160a01b038116610e665760405163e6c4247b60e01b815260040160405180910390fd5b600080610e738585611ded565b9150915080600014610ed957610e89838261130c565b6001600160a01b038316336001600160a01b03167ffc85082516ca8fe95d78404d69723bc9f7f40661fbf2ea20dbdb14c2413d5ea6878785604051610ed09392919061254b565b60405180910390a35b600254610f0090600160281b90046001600160a01b0316846001600160581b038516612003565b6001600160a01b038316336001600160a01b03167f54ebfb5e1ba02edcdc895d6b0a7238fb8a3f5798ee21012225cb6d5b80d8c2a7878786604051610f4793929190612617565b60405180910390a35050505050565b610f5e611a62565b6001600160a01b038116610f855760405163e6c4247b60e01b815260040160405180910390fd5b610fa0600254600160281b90046001600160a01b0316151590565b15610fbe5760405163d9b9141960e01b815260040160405180910390fd5b6002805465010000000000600160c81b031916600160281b6001600160a01b038416908102919091179091556001600052600460209081527fabd6e7cb50984ff9c2f3e18a2660c3353dadf4e3291deeb275dae2cd1e44fe0580546001600160a81b031916426001600160a81b03161790556040519182527f908408e307fc569b417f6cbec5d5a06f44a0a505ac0479b47d421a4b2fd6a1e6910160405180910390a150565b61106c6118d7565b600254610100900463ffffffff16600081815260046020526040812054600160a81b90046001600160581b03166110b4347002f050fe938943acc45f65568000000000612644565b6110be919061265b565b63ffffffff83166000908152600460205260408120600101805492935083929091906110eb9084906125ca565b909155506110f9905061191f565b63ffffffff82166000818152600460205260409081902090517f07c9d3a8bea400ee1980880fb7f4e3532e56612ff7e6c67e7096e1b3c20818ff9161116691349082546001600160a81b038116825260a81c60208201526001909201546040830152606082015260800190565b60405180910390a25050565b60006001600160a01b03821661119b5760405163e6c4247b60e01b815260040160405180910390fd5b506001600160a01b031660009081526001602052604090205490565b6111bf611a62565b6001600160a01b0381166111e957604051631e4fbdf760e01b815260006004820152602401610687565b6111f281611a8f565b50565b60008161120181611654565b600061120c336105ca565b600254909150610100900463ffffffff1660005b838110156112e15786868281811061123a5761123a6125b4565b90506020020135831161125957868682818110610664576106646125b4565b61126f338888848181106106a6576106a66125b4565b61127990866125ca565b336000908152600360205260409020909550829088888481811061129f5761129f6125b4565b90506020020135815481106112b6576112b66125b4565b6000918252602090912001805463ffffffff191663ffffffff92909216919091179055600101611220565b508360000361130357604051630fec21fd60e21b815260040160405180910390fd5b50505092915050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611359576040519150601f19603f3d011682016040523d82523d6000602084013e61135e565b606091505b505090508061138057604051633d2cec6f60e21b815260040160405180910390fd5b505050565b60408051600280825260608201835260009283929190602083019080368337019050509050737a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611420919061267d565b81600081518110611433576114336125b4565b6001600160a01b0392831660209182029290920101526002548251600160281b909104909116908290600190811061146d5761146d6125b4565b6001600160a01b0390921660209283029190910190910152604051637ff36ab560e01b8152600090737a250d5630b4cf539739df2c5dacb4c659f2488d90637ff36ab59087906114d0906001600160581b0389169087903090429060040161269a565b60006040518083038185885af11580156114ee573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526115179190810190612704565b90508060018151811061152c5761152c6125b4565b60200260200101519250505092915050565b604080518082019091526000808252602082015260025460009061156e90610100900463ffffffff1660016125dd565b6040805180820190915263ffffffff821681526001600160581b03851660208201529250905060036000336001600160a01b03168152602080820192909252604090810160009081208054600181018255908252838220865191018054878601516001600160581b03908116640100000000026effffffffffffffffffffffffffffff1990921663ffffffff948516179190911790915590851682526004909352208054859260159161162a918591600160a81b9004166127c2565b92506101000a8154816001600160581b0302191690836001600160581b0316021790555050919050565b80158061166257506101f481115b156111f257604051634ec4810560e11b815260040160405180910390fd5b6001600160a01b03821660009081526003602052604081208054829190849081106116ad576116ad6125b4565b60009182526020909120015463ffffffff1690508015806116de575060025463ffffffff8083166101009092041611155b156116ed57600091505061096f565b7002f050fe938943acc45f655680000000006004600061170e6001856127e2565b63ffffffff1663ffffffff16815260200190815260200160002060010154600460006001600260019054906101000a900463ffffffff1661174f91906127e2565b63ffffffff1663ffffffff168152602001908152602001600020600101546117779190612506565b6001600160a01b03861660009081526003602052604090208054869081106117a1576117a16125b4565b6000918252602090912001546117c8919064010000000090046001600160581b0316612644565b6117d2919061265b565b949350505050565b80156118255781841061180057604051630e0d5b9360e21b815260040160405180910390fd5b81831061182057604051631a38ee6360e21b815260040160405180910390fd5b611879565b83158061183157508184115b1561184f57604051630e0d5b9360e21b815260040160405180910390fd5b82158061185b57508183115b1561187957604051631a38ee6360e21b815260040160405180910390fd5b8284111561189a57604051630e0d5b9360e21b815260040160405180910390fd5b6101f46118a78585612506565b6118b29060016125ca565b11156118d1576040516328e2aa3760e01b815260040160405180910390fd5b50505050565b337f00000000000000000000000034bccf4af03870265fe99cec262524f343cca7ff6001600160a01b031614610b66576040516282b42960e81b815260040160405180910390fd5b60006002600181819054906101000a900463ffffffff1661193f906127ff565b825463ffffffff8083166101009490940a848102910219909116179092556000908152600460208190526040822080546001600160a81b0319166001600160581b0342161790559192506119946001846127e2565b63ffffffff1663ffffffff16815260200190815260200160002060010154600460008363ffffffff1663ffffffff16815260200190815260200160002060010181905550600460006001836119e991906127e2565b63ffffffff9081168252602080830193909352604091820160009081205491851681526004909352912080546001600160581b03600160a81b93849004811693601592611a3b928692909104166127c2565b92506101000a8154816001600160581b0302191690836001600160581b0316021790555050565b6000546001600160a01b03163314610b665760405163118cdaa760e01b8152336004820152602401610687565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6002546001600160581b03821690600160281b90046001600160a01b03166370a08231336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611b47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6b9190612822565b1015611c2c5733600254600160281b90046001600160a01b03166370a08231336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611bcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf39190612822565b60405163391434e360e21b81526001600160a01b03909216600483015260248201526001600160581b0382166044820152606401610687565b6002546001600160581b03821690600160281b90046001600160a01b031663dd62ed3e336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604401602060405180830381865afa158015611c9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cbe9190612822565b10156111f2576002543090600160281b90046001600160a01b031663dd62ed3e336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604401602060405180830381865afa158015611d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d4d9190612822565b604051637dc7a0d960e11b81526001600160a01b03909216600483015260248201526001600160581b0382166044820152606401610687565b6040516001600160a01b0384811660248301528381166044830152606482018390526118d19186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612034565b60008082611dfa81611654565b6000611e05336105ca565b600254909150610100900463ffffffff1660005b83811015611ff757878782818110611e3357611e336125b4565b905060200201358311611e5257878782818110610664576106646125b4565b611e68338989848181106106a6576106a66125b4565b611e7290866125ca565b33600090815260036020526040812091965090898984818110611e9757611e976125b4565b9050602002013581548110611eae57611eae6125b4565b600091825260208083206040805180820190915292015463ffffffff81168084526401000000009091046001600160581b0316918301919091529092509003611f0a5760405163d9b9141960e01b815260040160405180910390fd5b3360009081526003602052604081208a8a85818110611f2b57611f2b6125b4565b9050602002013581548110611f4257611f426125b4565b6000918252602080832091909101805463ffffffff191663ffffffff9485161790558301518351909260049291811690871610611f7f5785611f82565b83515b63ffffffff16815260208101919091526040016000208054601590611fb8908490600160a81b90046001600160581b031661283b565b92506101000a8154816001600160581b0302191690836001600160581b03160217905550806020015187611fec91906127c2565b965050600101611e19565b505050505b9250929050565b6040516001600160a01b0383811660248301526044820183905261138091859182169063a9059cbb90606401611dbb565b60006120496001600160a01b03841683612097565b9050805160001415801561206e57508080602001905181019061206c919061285b565b155b1561138057604051635274afe760e01b81526001600160a01b0384166004820152602401610687565b60606106ca8383600084600080856001600160a01b031684866040516120bd919061287d565b60006040518083038185875af1925050503d80600081146120fa576040519150601f19603f3d011682016040523d82523d6000602084013e6120ff565b606091505b509150915061210f868383612119565b9695505050505050565b60608261212e5761212982612175565b6106ca565b815115801561214557506001600160a01b0384163b155b1561216e57604051639996b31560e01b81526001600160a01b0385166004820152602401610687565b50806106ca565b8051156121855780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b60008083601f8401126121b057600080fd5b50813567ffffffffffffffff8111156121c857600080fd5b6020830191508360208260051b8501011115611ffc57600080fd5b80356001600160581b03811681146121fa57600080fd5b919050565b6001600160a01b03811681146111f257600080fd5b60008060008060006080868803121561222c57600080fd5b853567ffffffffffffffff81111561224357600080fd5b61224f8882890161219e565b90965094505060208601359250612268604087016121e3565b91506060860135612278816121ff565b809150509295509295909350565b60006020828403121561229857600080fd5b81356106ca816121ff565b6000806000604084860312156122b857600080fd5b83356122c3816121ff565b9250602084013567ffffffffffffffff8111156122df57600080fd5b6122eb8682870161219e565b9497909650939450505050565b60006020828403121561230a57600080fd5b813563ffffffff811681146106ca57600080fd5b81516001600160a81b031681526020808301516001600160581b031690820152604080830151908201526060810161096f565b60008060006060848603121561236657600080fd5b8335612371816121ff565b95602085013595506040909401359392505050565b602080825282518282018190526000919060409081850190868401855b828110156123df576123cf848351805163ffffffff1682526020908101516001600160581b0316910152565b92840192908501906001016123a3565b5091979650505050505050565b600080604083850312156123ff57600080fd5b823561240a816121ff565b946020939093013593505050565b815163ffffffff1681526020808301516001600160581b0316908201526040810161096f565b60008060006040848603121561245357600080fd5b833567ffffffffffffffff81111561246a57600080fd5b6124768682870161219e565b909450925050602084013561248a816121ff565b809150509250925092565b6000602082840312156124a757600080fd5b6106ca826121e3565b63ffffffff83168152608081016106ca602083018480516001600160a81b031682526020808201516001600160581b031690830152604090810151910152565b634e487b7160e01b600052601160045260246000fd5b8181038181111561096f5761096f6124f0565b81835260006001600160fb1b0383111561253257600080fd5b8260051b80836020870137939093016020019392505050565b60408152600061255f604083018587612519565b9050826020830152949350505050565b608081526000612583608083018688612519565b6020838101869052845163ffffffff1660408501528401516001600160581b03166060840152905095945050505050565b634e487b7160e01b600052603260045260246000fd5b8082018082111561096f5761096f6124f0565b63ffffffff8181168382160190808211156125fa576125fa6124f0565b5092915050565b634e487b7160e01b600052604160045260246000fd5b60408152600061262b604083018587612519565b90506001600160581b0383166020830152949350505050565b808202811582820484141761096f5761096f6124f0565b60008261267857634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561268f57600080fd5b81516106ca816121ff565b600060808201868352602060808185015281875180845260a086019150828901935060005b818110156126e45784516001600160a01b0316835293830193918301916001016126bf565b50506001600160a01b039690961660408501525050506060015292915050565b6000602080838503121561271757600080fd5b825167ffffffffffffffff8082111561272f57600080fd5b818501915085601f83011261274357600080fd5b81518181111561275557612755612601565b8060051b604051601f19603f8301168101818110858211171561277a5761277a612601565b60405291825284820192508381018501918883111561279857600080fd5b938501935b828510156127b65784518452938501939285019261279d565b98975050505050505050565b6001600160581b038181168382160190808211156125fa576125fa6124f0565b63ffffffff8281168282160390808211156125fa576125fa6124f0565b600063ffffffff808316818103612818576128186124f0565b6001019392505050565b60006020828403121561283457600080fd5b5051919050565b6001600160581b038281168282160390808211156125fa576125fa6124f0565b60006020828403121561286d57600080fd5b815180151581146106ca57600080fd5b6000825160005b8181101561289e5760208186018101518583015201612884565b50600092019182525091905056fea2646970667358221220cac8aa0db0d4c153dc7d9a55b395d376e7c33a0eef119eec1cb3a7ad113fa24464736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000adedc7487c59ece60178cf69b8df7e3c4730d9000000000000000000000000034bccf4af03870265fe99cec262524f343cca7ff
-----Decoded View---------------
Arg [0] : _multiSigAdmin (address): 0x0adEDC7487c59eCe60178Cf69b8DF7E3c4730d90
Arg [1] : revenueDistributor_ (address): 0x34BCcF4aF03870265Fe99cEc262524F343Cca7ff
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000adedc7487c59ece60178cf69b8df7e3c4730d90
Arg [1] : 00000000000000000000000034bccf4af03870265fe99cec262524f343cca7ff
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.