More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 4,326 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Zap Stake | 16595101 | 651 days ago | IN | 0.025 ETH | 0.00497728 | ||||
Zap Stake | 16592069 | 652 days ago | IN | 0 ETH | 0.01236823 | ||||
Zap Stake | 16571619 | 655 days ago | IN | 0 ETH | 0.01149539 | ||||
Zap Stake | 16571159 | 655 days ago | IN | 0.25 ETH | 0.00804121 | ||||
Zap Stake | 16559350 | 656 days ago | IN | 0.009 ETH | 0.00368257 | ||||
Zap Stake | 16554015 | 657 days ago | IN | 0.2 ETH | 0.00697493 | ||||
Zap Stake | 16553972 | 657 days ago | IN | 0 ETH | 0.01055757 | ||||
Zap Stake | 16539084 | 659 days ago | IN | 0 ETH | 0.00574975 | ||||
Zap Stake | 16536984 | 660 days ago | IN | 0.08 ETH | 0.01009427 | ||||
Zap Stake | 16521664 | 662 days ago | IN | 0 ETH | 0.02844253 | ||||
Zap Stake | 16521168 | 662 days ago | IN | 2.33 ETH | 0.00619875 | ||||
Zap Stake | 16519256 | 662 days ago | IN | 6 ETH | 0.00477994 | ||||
Zap Stake | 16517924 | 662 days ago | IN | 0 ETH | 0.00422442 | ||||
Zap Stake | 16516268 | 662 days ago | IN | 0 ETH | 0.01088146 | ||||
Zap Stake | 16514911 | 663 days ago | IN | 0.07 ETH | 0.00463663 | ||||
Zap Stake | 16513902 | 663 days ago | IN | 0 ETH | 0.00842138 | ||||
Zap Stake | 16480710 | 667 days ago | IN | 0 ETH | 0.00514583 | ||||
Zap Stake | 16472256 | 669 days ago | IN | 0 ETH | 0.00630464 | ||||
Zap Stake | 16466844 | 669 days ago | IN | 0.0703 ETH | 0.00381219 | ||||
Zap Stake | 16450578 | 672 days ago | IN | 2.25 ETH | 0.02374458 | ||||
Zap Stake | 16444279 | 672 days ago | IN | 0.0203 ETH | 0.00339 | ||||
Zap Stake | 16420403 | 676 days ago | IN | 0 ETH | 0.00713956 | ||||
Zap Stake | 16419699 | 676 days ago | IN | 0 ETH | 0.00559409 | ||||
Zap Stake | 16419041 | 676 days ago | IN | 0.12 ETH | 0.004455 | ||||
Zap Stake | 16330261 | 688 days ago | IN | 0.012 ETH | 0.00344368 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
16595101 | 651 days ago | 0.025 ETH | ||||
16571159 | 655 days ago | 0.25 ETH | ||||
16559350 | 656 days ago | 0.009 ETH | ||||
16554015 | 657 days ago | 0.2 ETH | ||||
16536984 | 660 days ago | 0.08 ETH | ||||
16521168 | 662 days ago | 2.33 ETH | ||||
16519256 | 662 days ago | 6 ETH | ||||
16514911 | 663 days ago | 0.07 ETH | ||||
16466844 | 669 days ago | 0.0703 ETH | ||||
16450578 | 672 days ago | 2.25 ETH | ||||
16444279 | 672 days ago | 0.0203 ETH | ||||
16419041 | 676 days ago | 0.12 ETH | ||||
16330261 | 688 days ago | 0.012 ETH | ||||
16266085 | 697 days ago | 0.12 ETH | ||||
16263138 | 698 days ago | 2.052 ETH | ||||
16261040 | 698 days ago | 44 ETH | ||||
16201991 | 706 days ago | 202.5 ETH | ||||
16155227 | 713 days ago | 0.045 ETH | ||||
16117425 | 718 days ago | 3.4 ETH | ||||
16117421 | 718 days ago | 0.001 ETH | ||||
16115788 | 718 days ago | 0.065 ETH | ||||
16104689 | 720 days ago | 0.0005 ETH | ||||
16103707 | 720 days ago | 0.16 ETH | ||||
16103536 | 720 days ago | 0.06 ETH | ||||
16101514 | 720 days ago | 0.012 ETH |
Loading...
Loading
Contract Name:
Olympus_V2_Zap_In
Compiler Version
v0.8.4+commit.c7e474f2
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-or-later /// @title Olympus V2 Zap In /// @author Zapper, Cryptonomik, Dionysus /// Review by: ZayenX /// Copyright (C) 2021 Zapper /// Copyright (C) 2022 OlympusDAO pragma solidity 0.8.4; import "./interfaces/IBondDepoV2.sol"; import "./interfaces/IStakingV2.sol"; import "./interfaces/IsOHMv2.sol"; import "./interfaces/IgOHM.sol"; import "./libraries/ZapBaseV3.sol"; contract Olympus_V2_Zap_In is ZapBaseV3 { using SafeERC20 for IERC20; ////////////////////////// STORAGE ////////////////////////// address public depo; address public staking; address public immutable OHM; address public immutable sOHM; address public immutable gOHM; ////////////////////////// EVENTS ////////////////////////// // Emitted when `sender` successfully calls ZapStake event zapStake(address sender, address token, uint256 tokensRec, address referral); // Emitted when `sender` successfully calls ZapBond event zapBond(address sender, address token, uint256 tokensRec, address referral); ////////////////////////// CONSTRUCTION ////////////////////////// constructor( address _depo, address _staking, address _OHM, address _sOHM, address _gOHM ) ZapBaseV3(0, 0) { // 0x Proxy approvedTargets[0xDef1C0ded9bec7F1a1670819833240f027b25EfF] = true; depo = _depo; staking = _staking; OHM = _OHM; sOHM = _sOHM; gOHM = _gOHM; } ////////////////////////// PUBLIC ////////////////////////// /// @notice This function acquires OHM with ETH or ERC20 tokens and stakes it for sOHM/gOHM /// @param fromToken The token used for entry (address(0) if ether) /// @param amountIn The quantity of fromToken being sent /// @param toToken The token fromToken is being converted to (i.e. sOHM or gOHM) /// @param minToToken The minimum acceptable quantity sOHM or gOHM to receive. Reverts otherwise /// @param swapTarget Excecution target for the swap /// @param swapData DEX swap data /// @param referral The front end operator address /// @return OHMRec The quantity of sOHM or gOHM received (depending on toToken) function ZapStake( address fromToken, uint256 amountIn, address toToken, uint256 minToToken, address swapTarget, bytes calldata swapData, address referral ) external payable pausable returns (uint256 OHMRec) { // pull users fromToken uint256 toInvest = _pullTokens(fromToken, amountIn, referral, true); // swap fromToken -> OHM uint256 tokensBought = _fillQuote(fromToken, OHM, toInvest, swapTarget, swapData); // stake OHM for sOHM or gOHM OHMRec = _stake(tokensBought, toToken); // Slippage check require(OHMRec > minToToken, "High Slippage"); emit zapStake(msg.sender, toToken, OHMRec, referral); } /// @notice This function acquires Olympus bonds with ETH or ERC20 tokens /// @param fromToken The token used for entry (address(0) if ether) /// @param amountIn The quantity of fromToken being sent /// @param principal The token fromToken is being converted to (i.e. token or LP to bond) /// @param swapTarget Excecution target for the swap or Zap /// @param swapData DEX or Zap data /// @param referral The front end operator address /// @param maxPrice The maximum price at which to buy the bond /// @param bondId The ID of the market /// @return OHMRec The quantity of gOHM due function ZapBond( address fromToken, uint256 amountIn, address principal, address swapTarget, bytes calldata swapData, address referral, uint256 maxPrice, uint256 bondId ) external payable pausable returns (uint256 OHMRec) { // pull users fromToken uint256 toInvest = _pullTokens(fromToken, amountIn, referral, true); // swap fromToken -> bond principal uint256 tokensBought = _fillQuote( fromToken, principal, // to token toInvest, swapTarget, swapData ); // make sure bond depo is approved to spend this contracts "principal" _approveToken(principal, depo, tokensBought); // purchase bond (OHMRec, , ) = IBondDepoV2(depo).deposit( bondId, tokensBought, maxPrice, msg.sender, // depositor referral ); emit zapBond(msg.sender, principal, OHMRec, referral); } ////////////////////////// INTERNAL ////////////////////////// /// @param amount The quantity of OHM being staked /// @param toToken Either sOHM or gOHM /// @return OHMRec quantity of sOHM or gOHM received (depending on toToken) function _stake(uint256 amount, address toToken) internal returns (uint256) { uint256 claimedTokens; // approve staking for OHM if needed _approveToken(OHM, staking, amount); if (toToken == gOHM) { // stake OHM -> gOHM claimedTokens = IStaking(staking).stake(address(this), amount, false, true); IERC20(toToken).safeTransfer(msg.sender, claimedTokens); return claimedTokens; } // stake OHM -> sOHM claimedTokens = IStaking(staking).stake(address(this), amount, true, true); IERC20(toToken).safeTransfer(msg.sender, claimedTokens); return claimedTokens; } ////////////////////////// OLYMPUS ONLY ////////////////////////// /// @notice update state for staking function update_Staking(address _staking) external onlyOwner { staking = _staking; } /// @notice update state for depo function update_Depo(address _depo) external onlyOwner { depo = _depo; } }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.0; import "./interfaces/IBondDepoV2.sol"; contract BondHelper { ////////////////////////// STORAGE ////////////////////////// /// @notice used for access control address public olympusDAO; /// @notice needed since we can't access IDS length in v2 bond depo mapping(address => uint16) public principalToBID; /// @notice stores all principals for ohm depo address[] public principals; /// @notice V2 olympus bond depository IBondDepoV2 public depov2; ////////////////////////// MODIFIERS ////////////////////////// modifier onlyOlympusDAO() { require(msg.sender == olympusDAO, "Only OlympusDAO"); _; } ////////////////////////// CONSTRUCTOR ////////////////////////// constructor(address[] memory _principals, IBondDepoV2 _depov2) { principals = _principals; depov2 = _depov2; // access control set to deployer temporarily // so that we can setup state. olympusDAO = msg.sender; } ////////////////////////// PUBLIC VIEW ////////////////////////// /// @notice returns (cheap bond ID, principal) function getCheapestBID() external view returns (uint16, address) { // set cheapest price to a very large number so we can check against it uint256 cheapestPrice = type(uint256).max; uint16 cheapestBID; address cheapestPrincipal; for (uint256 i; i < principals.length; i++) { uint16 BID = principalToBID[principals[i]]; uint256 price = IBondDepoV2(depov2).bondPriceInUSD(BID); if (price <= cheapestPrice && _isBondable(BID)) { cheapestPrice = price; cheapestBID = BID; cheapestPrincipal = principals[i]; } } return (cheapestBID, cheapestPrincipal); } function getBID(address principal) external view returns (uint16) { uint16 BID = principalToBID[principal]; if (_isBondable(BID)) return BID; revert("Unsupported principal"); } function _isBondable(uint16 _BID) public view returns (bool) { (, , uint256 totalDebt_, ) = depov2.bondInfo(_BID); (, , , , uint256 maxDebt_) = depov2.bondTerms(_BID); bool soldOut = totalDebt_ == maxDebt_; return !soldOut; } ////////////////////////// ONLY OLYMPUS ////////////////////////// function update_OlympusDAO(address _newOlympusDAO) external onlyOlympusDAO { olympusDAO = _newOlympusDAO; } function update_principalToBondId(address _principal, uint16 _bondId) external onlyOlympusDAO { principalToBID[_principal] = _bondId; } function update_principals(address[] memory _principals) external onlyOlympusDAO { principals = _principals; } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; interface IBondDepoV2 { /** * @notice deposit bond * @param _bid uint256 * @param _amount uint256 * @param _maxPrice uint256 * @param _depositor address * @param _feo address * @return payout_ uint256 * @return expiry_ uint256 * @return index_ uint256 */ function deposit( uint256 _bid, uint256 _amount, uint256 _maxPrice, address _depositor, address _feo ) external returns ( uint256 payout_, uint256 expiry_, uint16 index_ ); function marketPrice(uint256 _id) external view returns (uint256); function bondPriceInUSD(uint16 _bid) external view returns (uint256); /** * @notice returns data about a bond type * @param _BID uint * @return principal_ address * @return calculator_ address * @return totalDebt_ uint * @return lastBondCreatedAt_ uint */ function bondInfo(uint256 _BID) external view returns ( address principal_, address calculator_, uint256 totalDebt_, uint256 lastBondCreatedAt_ ); /** * @notice returns terms for a bond type * @param _BID uint * @return controlVariable_ uint * @return vestingTerm_ uint * @return minimumPrice_ uint * @return maxPayout_ uint * @return maxDebt_ uint */ function bondTerms(uint256 _BID) external view returns ( uint256 controlVariable_, uint256 vestingTerm_, uint256 minimumPrice_, uint256 maxPayout_, uint256 maxDebt_ ); function indexesFor(address _user) external view returns (uint256[] memory); function liveMarkets() external view returns (uint256[] memory); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.0; interface IStaking { function stake( address _to, uint256 _amount, bool _rebasing, bool _claim ) external returns (uint256); function claim(address _recipient, bool _rebasing) external returns (uint256); function forfeit() external returns (uint256); function toggleLock() external; function unstake( address _to, uint256 _amount, bool _trigger, bool _rebasing ) external returns (uint256); function wrap(address _to, uint256 _amount) external returns (uint256 gBalance_); function unwrap(address _to, uint256 _amount) external returns (uint256 sBalance_); function rebase() external; function index() external view returns (uint256); function contractBalance() external view returns (uint256); function totalStaked() external view returns (uint256); function supplyInWarmup() external view returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.0; import "./IERC20.sol"; interface IsOHM is IERC20 { function rebase(uint256 ohmProfit_, uint256 epoch_) external returns (uint256); function circulatingSupply() external view returns (uint256); function gonsForBalance(uint256 amount) external view returns (uint256); function balanceForGons(uint256 gons) external view returns (uint256); function index() external view returns (uint256); function toG(uint256 amount) external view returns (uint256); function fromG(uint256 amount) external view returns (uint256); function changeDebt( uint256 amount, address debtor, bool add ) external; function debtBalances(address _address) external view returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.0; import "./IERC20.sol"; interface IgOHM is IERC20 { function mint(address _to, uint256 _amount) external; function burn(address _from, uint256 _amount) external; function index() external view returns (uint256); function balanceFrom(uint256 _amount) external view returns (uint256); function balanceTo(uint256 _amount) external view returns (uint256); function migrate(address _staking, address _sOHM) external; }
// ███████╗░█████╗░██████╗░██████╗░███████╗██████╗░░░░███████╗██╗ // ╚════██║██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔══██╗░░░██╔════╝██║ // ░░███╔═╝███████║██████╔╝██████╔╝█████╗░░██████╔╝░░░█████╗░░██║ // ██╔══╝░░██╔══██║██╔═══╝░██╔═══╝░██╔══╝░░██╔══██╗░░░██╔══╝░░██║ // ███████╗██║░░██║██║░░░░░██║░░░░░███████╗██║░░██║██╗██║░░░░░██║ // ╚══════╝╚═╝░░╚═╝╚═╝░░░░░╚═╝░░░░░╚══════╝╚═╝░░╚═╝╚═╝╚═╝░░░░░╚═╝ // Copyright (C) 2021 zapper // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // /// @author Zapper /// @notice This abstract contract, which is inherited by Zaps, /// provides utility functions for moving tokens, checking allowances /// and balances, performing swaps and other Zaps, and accounting /// for fees. // SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.0; import "../interfaces/IERC20.sol"; import "../interfaces/IERC20Metadata.sol"; import "../interfaces/IWETH.sol"; import "./Context.sol"; import "./Address.sol"; import "./SafeERC20.sol"; // Ownable left here as not to confuse Olympus's Ownable abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } abstract contract ZapBaseV3 is Ownable { using SafeERC20 for IERC20; bool public stopped; address private constant wethTokenAddress = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // if true, goodwill is not deducted mapping(address => bool) public feeWhitelist; uint256 public goodwill; // % share of goodwill (0-100 %) uint256 affiliateSplit; // restrict affiliates mapping(address => bool) public affiliates; // affiliate => token => amount mapping(address => mapping(address => uint256)) public affiliateBalance; // token => amount mapping(address => uint256) public totalAffiliateBalance; // swapTarget => approval status mapping(address => bool) public approvedTargets; address internal constant ETHAddress = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; modifier pausable() { require(!stopped, "Paused"); _; } constructor(uint256 _goodwill, uint256 _affiliateSplit) { goodwill = _goodwill; affiliateSplit = _affiliateSplit; } /** @dev Transfers tokens (including ETH) from msg.sender to this contract @dev For use with Zap Ins (takes fee from input if > 0) @param token The ERC20 token to transfer to this contract (0 address if ETH) @return Quantity of tokens transferred to this contract */ function _pullTokens( address token, uint256 amount, address affiliate, bool enableGoodwill ) internal virtual returns (uint256) { uint256 totalGoodwillPortion; if (token == address(0)) { require(msg.value > 0, "No ETH sent"); totalGoodwillPortion = _subtractGoodwill( ETHAddress, msg.value, affiliate, enableGoodwill ); return msg.value - totalGoodwillPortion; } require(amount > 0, "Invalid token amount"); require(msg.value == 0, "ETH sent with token"); IERC20(token).safeTransferFrom(msg.sender, address(this), amount); totalGoodwillPortion = _subtractGoodwill(token, amount, affiliate, enableGoodwill); return amount - totalGoodwillPortion; } /** @dev Transfers tokens from msg.sender to this contract @dev For use with Zap Outs (does not transfer ETH) @param token The ERC20 token to transfer to this contract @return Quantity of tokens transferred to this contract */ function _pullTokens(address token, uint256 amount) internal virtual returns (uint256) { IERC20(token).safeTransferFrom(msg.sender, address(this), amount); return amount; } /** @dev Fulfills an encoded swap or Zap if the target is approved @param fromToken The sell token @param toToken The buy token @param amount The quantity of fromToken to sell @param swapTarget The execution target for the swapData @param swapData The swap data encoding the swap or Zap @return amountBought Quantity of tokens toToken acquired */ function _fillQuote( address fromToken, address toToken, uint256 amount, address swapTarget, bytes memory swapData ) internal virtual returns (uint256 amountBought) { if (fromToken == toToken) { return amount; } if (fromToken == address(0) && toToken == wethTokenAddress) { IWETH(wethTokenAddress).deposit{ value: amount }(); return amount; } if (fromToken == wethTokenAddress && toToken == address(0)) { IWETH(wethTokenAddress).withdraw(amount); return amount; } uint256 valueToSend; if (fromToken == address(0)) { valueToSend = amount; } else { _approveToken(fromToken, swapTarget, amount); } uint256 initialBalance = _getBalance(toToken); require(approvedTargets[swapTarget], "Target not Authorized"); (bool success, ) = swapTarget.call{ value: valueToSend }(swapData); require(success, "Error Swapping Tokens"); amountBought = _getBalance(toToken) - initialBalance; require(amountBought > 0, "Swapped To Invalid Token"); } /** @notice Gets this contract's balance of a token @param token The ERC20 token to check the balance of (0 address if ETH) @return balance This contract's token balance */ function _getBalance(address token) internal view returns (uint256 balance) { if (token == address(0)) { balance = address(this).balance; } else { balance = IERC20(token).balanceOf(address(this)); } } /** @notice Approve a token for spending with infinite allowance @param token The ERC20 token to approve @param spender The spender of the token */ function _approveToken(address token, address spender) internal { if (token == address(0) || spender == address(0)) return; IERC20 _token = IERC20(token); if (_token.allowance(address(this), spender) > 0) return; else { _token.safeApprove(spender, type(uint256).max); } } /** @notice Approve a token for spending with finite allowance @param token The ERC20 token to approve @param spender The spender of the token @param amount The allowance to grant to the spender */ function _approveToken( address token, address spender, uint256 amount ) internal { if (token == address(0) || spender == address(0)) return; IERC20(token).safeApprove(spender, 0); IERC20(token).safeApprove(spender, amount); } /** @notice Set address to true to bypass fees when calling this contract @param zapAddress The Zap caller which is allowed to bypass fees (if > 0) @param status The whitelisted status (true if whitelisted) */ function set_feeWhitelist(address zapAddress, bool status) external onlyOwner { feeWhitelist[zapAddress] = status; } /** @notice Sets a goodwill amount @param _new_goodwill The new goodwill amount between 0-1% */ function set_new_goodwill(uint256 _new_goodwill) public onlyOwner { require(_new_goodwill >= 0 && _new_goodwill <= 100, "GoodWill Value not allowed"); goodwill = _new_goodwill; } /** @notice Sets the percentage to split the goodwill by to distribute * to affiliates @param _new_affiliateSplit The new affiliate split between 0-1% */ function set_new_affiliateSplit(uint256 _new_affiliateSplit) external onlyOwner { require(_new_affiliateSplit <= 100, "Affiliate Split Value not allowed"); affiliateSplit = _new_affiliateSplit; } /** @notice Adds or removes an affiliate @param _affiliate The affiliate's address @param _status The affiliate's approval status */ function set_affiliate(address _affiliate, bool _status) external onlyOwner { affiliates[_affiliate] = _status; } /** @notice Withdraws goodwill share, retaining affilliate share @param tokens An array of the tokens to withdraw (0xeee address if ETH) */ function withdrawTokens(address[] calldata tokens) external onlyOwner { for (uint256 i = 0; i < tokens.length; i++) { uint256 qty; if (tokens[i] == ETHAddress) { qty = address(this).balance - totalAffiliateBalance[tokens[i]]; Address.sendValue(payable(owner()), qty); } else { qty = IERC20(tokens[i]).balanceOf(address(this)) - totalAffiliateBalance[tokens[i]]; IERC20(tokens[i]).safeTransfer(owner(), qty); } } } /** @notice Withdraws the affilliate share, retaining goodwill share @param tokens An array of the tokens to withdraw (0xeee address if ETH) */ function affilliateWithdraw(address[] calldata tokens) external { uint256 tokenBal; for (uint256 i = 0; i < tokens.length; i++) { tokenBal = affiliateBalance[msg.sender][tokens[i]]; affiliateBalance[msg.sender][tokens[i]] = 0; totalAffiliateBalance[tokens[i]] = totalAffiliateBalance[tokens[i]] - tokenBal; if (tokens[i] == ETHAddress) { Address.sendValue(payable(msg.sender), tokenBal); } else { IERC20(tokens[i]).safeTransfer(msg.sender, tokenBal); } } } /** @dev Adds or removes an approved swapTarget * swapTargets should be Zaps and must not be tokens! @param targets An array of addresses of approved swapTargets */ function setApprovedTargets(address[] calldata targets, bool[] calldata isApproved) external onlyOwner { require(targets.length == isApproved.length, "Invalid Input length"); for (uint256 i = 0; i < targets.length; i++) { approvedTargets[targets[i]] = isApproved[i]; } } /** @dev Subtracts the goodwill amount from the `amount` param @param token The ERC20 token being sent (0 address if ETH) @param amount The quantity of the token being sent @param affiliate The affiliate's address @param enableGoodwill True if bypassing goodwill, false otherwise @return totalGoodwillPortion The quantity of `token` that should be * subtracted from `amount` */ function _subtractGoodwill( address token, uint256 amount, address affiliate, bool enableGoodwill ) internal returns (uint256 totalGoodwillPortion) { bool whitelisted = feeWhitelist[msg.sender]; if (goodwill > 0 && enableGoodwill && !whitelisted) { totalGoodwillPortion = (amount * goodwill) / 10000; if (affiliates[affiliate]) { if (token == address(0)) { token = ETHAddress; } uint256 affiliatePortion = (totalGoodwillPortion * affiliateSplit) / 100; affiliateBalance[affiliate][token] += affiliatePortion; totalAffiliateBalance[token] += affiliatePortion; } } } /** @dev Toggles the contract's active state */ function toggleContractActive() public onlyOwner { stopped = !stopped; } receive() external payable { require(msg.sender != tx.origin, "Do not send ETH directly"); } }
// SPDX-License-Identifier: WTFPL pragma solidity ^0.8.0; interface IERC20 { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.0; import "./IERC20.sol"; interface IERC20Metadata is IERC20 { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.0; interface IWETH { function deposit() external payable; function withdraw(uint256 wad) external; }
// SPDX-License-Identifier: WTFPL pragma solidity ^0.8.0; abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require( address(this).balance >= amount, "Address: insufficient balance" ); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require( success, "Address: unable to send value, recipient may have reverted" ); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue( target, data, value, "Address: low-level call with value failed" ); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require( address(this).balance >= value, "Address: insufficient balance for call" ); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall( target, data, "Address: low-level static call failed" ); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall( target, data, "Address: low-level delegate call failed" ); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) private pure returns (bytes memory) { if (success) { return returndata; } else { // 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 // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.0; import "../interfaces/IERC20.sol"; import "./Address.sol"; library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.transfer.selector, to, value) ); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value) ); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn( token, abi.encodeWithSelector(token.approve.selector, spender, value) ); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn( token, abi.encodeWithSelector( token.approve.selector, spender, newAllowance ) ); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require( oldAllowance >= value, "SafeERC20: decreased allowance below zero" ); uint256 newAllowance = oldAllowance - value; _callOptionalReturn( token, abi.encodeWithSelector( token.approve.selector, spender, newAllowance ) ); } } /** * @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, "SafeERC20: low-level call failed" ); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require( abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed" ); } } }
// ███████╗░█████╗░██████╗░██████╗░███████╗██████╗░░░░███████╗██╗ // ╚════██║██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔══██╗░░░██╔════╝██║ // ░░███╔═╝███████║██████╔╝██████╔╝█████╗░░██████╔╝░░░█████╗░░██║ // ██╔══╝░░██╔══██║██╔═══╝░██╔═══╝░██╔══╝░░██╔══██╗░░░██╔══╝░░██║ // ███████╗██║░░██║██║░░░░░██║░░░░░███████╗██║░░██║██╗██║░░░░░██║ // ╚══════╝╚═╝░░╚═╝╚═╝░░░░░╚═╝░░░░░╚══════╝╚═╝░░╚═╝╚═╝╚═╝░░░░░╚═╝ // Copyright (C) 2021 zapper // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // /// @author Zapper /// @notice This abstract contract, which is inherited by Zaps, /// provides utility functions for moving tokens, checking allowances /// and balances, performing swaps and other Zaps, and accounting /// for fees. // SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.0; import "../interfaces/IERC20.sol"; import "../interfaces/IERC20Metadata.sol"; import "../interfaces/IWETH.sol"; import "./Context.sol"; import "./Address.sol"; import "./SafeERC20.sol"; // Ownable left here as not to confuse Olympus's Ownable abstract contract Ownable is Context { address private _owner; event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require( newOwner != address(0), "Ownable: new owner is the zero address" ); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } abstract contract ZapBaseV2_2 is Ownable { using SafeERC20 for IERC20; bool public stopped; address private constant wethTokenAddress = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // if true, goodwill is not deducted mapping(address => bool) public feeWhitelist; uint256 public goodwill; // % share of goodwill (0-100 %) uint256 affiliateSplit; // restrict affiliates mapping(address => bool) public affiliates; // affiliate => token => amount mapping(address => mapping(address => uint256)) public affiliateBalance; // token => amount mapping(address => uint256) public totalAffiliateBalance; // swapTarget => approval status mapping(address => bool) public approvedTargets; address internal constant ETHAddress = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address internal constant ZapperAdmin = 0x3CE37278de6388532C3949ce4e886F365B14fB56; // circuit breaker modifiers modifier stopInEmergency { require(!stopped, "Paused"); _; } constructor(uint256 _goodwill, uint256 _affiliateSplit) { goodwill = _goodwill; affiliateSplit = _affiliateSplit; } /** @dev Transfers tokens (including ETH) from msg.sender to this contract @dev For use with Zap Ins (takes fee from input if > 0) @param token The ERC20 token to transfer to this contract (0 address if ETH) @return Quantity of tokens transferred to this contract */ function _pullTokens( address token, uint256 amount, address affiliate, bool enableGoodwill ) internal virtual returns (uint256) { uint256 totalGoodwillPortion; if (token == address(0)) { require(msg.value > 0, "No ETH sent"); totalGoodwillPortion = _subtractGoodwill( ETHAddress, msg.value, affiliate, enableGoodwill ); return msg.value - totalGoodwillPortion; } require(amount > 0, "Invalid token amount"); require(msg.value == 0, "ETH sent with token"); IERC20(token).safeTransferFrom(msg.sender, address(this), amount); totalGoodwillPortion = _subtractGoodwill( token, amount, affiliate, enableGoodwill ); return amount - totalGoodwillPortion; } /** @dev Transfers tokens from msg.sender to this contract @dev For use with Zap Outs (does not transfer ETH) @param token The ERC20 token to transfer to this contract @return Quantity of tokens transferred to this contract */ function _pullTokens(address token, uint256 amount) internal virtual returns (uint256) { IERC20(token).safeTransferFrom(msg.sender, address(this), amount); return amount; } /** @dev Fulfills an encoded swap or Zap if the target is approved @param fromToken The sell token @param toToken The buy token @param amount The quantity of fromToken to sell @param swapTarget The execution target for the swapData @param swapData The swap data encoding the swap or Zap @return amountBought Quantity of tokens toToken acquired */ function _fillQuote( address fromToken, address toToken, uint256 amount, address swapTarget, bytes memory swapData ) internal virtual returns (uint256 amountBought) { if (fromToken == toToken) { return amount; } if (fromToken == address(0) && toToken == wethTokenAddress) { IWETH(wethTokenAddress).deposit{ value: amount }(); return amount; } if (fromToken == wethTokenAddress && toToken == address(0)) { IWETH(wethTokenAddress).withdraw(amount); return amount; } uint256 valueToSend; if (fromToken == address(0)) { valueToSend = amount; } else { _approveToken(fromToken, swapTarget, amount); } uint256 initialBalance = _getBalance(toToken); require(approvedTargets[swapTarget], "Target not Authorized"); (bool success, ) = swapTarget.call{ value: valueToSend }(swapData); require(success, "Error Swapping Tokens"); amountBought = _getBalance(toToken) - initialBalance; require(amountBought > 0, "Swapped To Invalid Token"); } /** @notice Gets this contract's balance of a token @param token The ERC20 token to check the balance of (0 address if ETH) @return balance This contract's token balance */ function _getBalance(address token) internal view returns (uint256 balance) { if (token == address(0)) { balance = address(this).balance; } else { balance = IERC20(token).balanceOf(address(this)); } } /** @notice Approve a token for spending with infinite allowance @param token The ERC20 token to approve @param spender The spender of the token */ function _approveToken(address token, address spender) internal { IERC20 _token = IERC20(token); if (_token.allowance(address(this), spender) > 0) return; else { _token.safeApprove(spender, type(uint256).max); } } /** @notice Approve a token for spending with finite allowance @param token The ERC20 token to approve @param spender The spender of the token @param amount The allowance to grant to the spender */ function _approveToken( address token, address spender, uint256 amount ) internal { IERC20(token).safeApprove(spender, 0); IERC20(token).safeApprove(spender, amount); } /** @notice Set address to true to bypass fees when calling this contract @param zapAddress The Zap caller which is allowed to bypass fees (if > 0) @param status The whitelisted status (true if whitelisted) */ function set_feeWhitelist(address zapAddress, bool status) external onlyOwner { feeWhitelist[zapAddress] = status; } /** @notice Sets a goodwill amount @param _new_goodwill The new goodwill amount between 0-1% */ function set_new_goodwill(uint256 _new_goodwill) public onlyOwner { require( _new_goodwill >= 0 && _new_goodwill <= 100, "GoodWill Value not allowed" ); goodwill = _new_goodwill; } /** @notice Sets the percentage to split the goodwill by to distribute * to affiliates @param _new_affiliateSplit The new affiliate split between 0-1% */ function set_new_affiliateSplit(uint256 _new_affiliateSplit) external onlyOwner { require( _new_affiliateSplit <= 100, "Affiliate Split Value not allowed" ); affiliateSplit = _new_affiliateSplit; } /** @notice Adds or removes an affiliate @param _affiliate The affiliate's address @param _status The affiliate's approval status */ function set_affiliate(address _affiliate, bool _status) external onlyOwner { affiliates[_affiliate] = _status; } /** @notice Withdraws goodwill share, retaining affilliate share @param tokens An array of the tokens to withdraw (0xeee address if ETH) */ function withdrawTokens(address[] calldata tokens) external onlyOwner { for (uint256 i = 0; i < tokens.length; i++) { uint256 qty; if (tokens[i] == ETHAddress) { qty = address(this).balance - totalAffiliateBalance[tokens[i]]; Address.sendValue(payable(owner()), qty); } else { qty = IERC20(tokens[i]).balanceOf(address(this)) - totalAffiliateBalance[tokens[i]]; IERC20(tokens[i]).safeTransfer(owner(), qty); } } } /** @notice Withdraws the affilliate share, retaining goodwill share @param tokens An array of the tokens to withdraw (0xeee address if ETH) */ function affilliateWithdraw(address[] calldata tokens) external { uint256 tokenBal; for (uint256 i = 0; i < tokens.length; i++) { tokenBal = affiliateBalance[msg.sender][tokens[i]]; affiliateBalance[msg.sender][tokens[i]] = 0; totalAffiliateBalance[tokens[i]] = totalAffiliateBalance[tokens[i]] - tokenBal; if (tokens[i] == ETHAddress) { Address.sendValue(payable(msg.sender), tokenBal); } else { IERC20(tokens[i]).safeTransfer(msg.sender, tokenBal); } } } /** @dev Adds or removes an approved swapTarget * swapTargets should be Zaps and must not be tokens! @param targets An array of addresses of approved swapTargets */ function setApprovedTargets( address[] calldata targets, bool[] calldata isApproved ) external onlyOwner { require(targets.length == isApproved.length, "Invalid Input length"); for (uint256 i = 0; i < targets.length; i++) { approvedTargets[targets[i]] = isApproved[i]; } } /** @dev Subtracts the goodwill amount from the `amount` param @param token The ERC20 token being sent (0 address if ETH) @param amount The quantity of the token being sent @param affiliate The affiliate's address @param enableGoodwill True if bypassing goodwill, false otherwise @return totalGoodwillPortion The quantity of `token` that should be * subtracted from `amount` */ function _subtractGoodwill( address token, uint256 amount, address affiliate, bool enableGoodwill ) internal returns (uint256 totalGoodwillPortion) { bool whitelisted = feeWhitelist[msg.sender]; if (goodwill > 0 && enableGoodwill && !whitelisted) { totalGoodwillPortion = (amount * goodwill) / 10000; if (affiliates[affiliate]) { if (token == address(0)) { token = ETHAddress; } uint256 affiliatePortion = (totalGoodwillPortion * affiliateSplit) / 100; affiliateBalance[affiliate][token] += affiliatePortion; totalAffiliateBalance[token] += affiliatePortion; } } } /** @dev Toggles the contract's active state */ function toggleContractActive() public onlyOwner { stopped = !stopped; } receive() external payable { require(msg.sender != tx.origin, "Do not send ETH directly"); } }
// ███████╗░█████╗░██████╗░██████╗░███████╗██████╗░░░░███████╗██╗ // ╚════██║██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔══██╗░░░██╔════╝██║ // ░░███╔═╝███████║██████╔╝██████╔╝█████╗░░██████╔╝░░░█████╗░░██║ // ██╔══╝░░██╔══██║██╔═══╝░██╔═══╝░██╔══╝░░██╔══██╗░░░██╔══╝░░██║ // ███████╗██║░░██║██║░░░░░██║░░░░░███████╗██║░░██║██╗██║░░░░░██║ // ╚══════╝╚═╝░░╚═╝╚═╝░░░░░╚═╝░░░░░╚══════╝╚═╝░░╚═╝╚═╝╚═╝░░░░░╚═╝ // Copyright (C) 2021 zapper // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // /// @author Zapper and OlympusDAO /// @notice This contract enters/exits OlympusDAO Ω with/to any token. /// Bonds can also be created on behalf of msg.sender using any input token. // SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.0; import "./interfaces/IBondDepository.sol"; import "./interfaces/IStaking.sol"; import "./interfaces/IwsOHM.sol"; import "./libraries/ZapBaseV2_2.sol"; contract Olympus_Zap_V2 is ZapBaseV2_2 { using SafeERC20 for IERC20; /////////////// storage /////////////// address public olympusDAO; address public staking = 0xFd31c7d00Ca47653c6Ce64Af53c1571f9C36566a; address public constant OHM = 0x383518188C0C6d7730D91b2c03a03C837814a899; address public sOHM = 0x04F2694C8fcee23e8Fd0dfEA1d4f5Bb8c352111F; address public wsOHM = 0xCa76543Cf381ebBB277bE79574059e32108e3E65; // IE DAI => wanted payout token (IE OHM) => bond depo mapping(address => mapping(address => address)) public principalToDepository; /////////////// Events /////////////// // Emitted when `sender` Zaps In event zapIn(address sender, address token, uint256 tokensRec, address affiliate); // Emitted when `sender` Zaps Out event zapOut(address sender, address token, uint256 tokensRec, address affiliate); /////////////// Modifiers /////////////// modifier onlyOlympusDAO() { require(msg.sender == olympusDAO, "Only OlympusDAO"); _; } /////////////// Construction /////////////// constructor( uint256 _goodwill, uint256 _affiliateSplit, address _olympusDAO ) ZapBaseV2_2(_goodwill, _affiliateSplit) { // 0x Proxy approvedTargets[0xDef1C0ded9bec7F1a1670819833240f027b25EfF] = true; // Zapper Sushiswap Zap In approvedTargets[0x5abfbE56553a5d794330EACCF556Ca1d2a55647C] = true; // Zapper Uniswap V2 Zap In approvedTargets[0x6D9893fa101CD2b1F8D1A12DE3189ff7b80FdC10] = true; olympusDAO = _olympusDAO; transferOwnership(ZapperAdmin); } /** * @notice This function deposits assets into OlympusDAO with ETH or ERC20 tokens * @param fromToken The token used for entry (address(0) if ether) * @param amountIn The amount of fromToken to invest * @param toToken The token fromToken is getting converted to. * @param minToToken The minimum acceptable quantity sOHM * or wsOHM or principal tokens to receive. Reverts otherwise * @param swapTarget Excecution target for the swap or zap * @param swapData DEX or Zap data. Must swap to ibToken underlying address * @param affiliate Affiliate address * @param maxBondPrice Max price for a bond denominated in toToken/principal. Ignored if not bonding. * @param bond if toToken is being used to purchase a bond. * @return OHMRec quantity of sOHM or wsOHM received (depending on toToken) * or the quantity OHM vesting (if bond is true) */ function ZapIn( address fromToken, uint256 amountIn, address toToken, uint256 minToToken, address swapTarget, bytes calldata swapData, address affiliate, address bondPayoutToken, // ignored if not bonding uint256 maxBondPrice, // ignored if not bonding bool bond ) external payable stopInEmergency returns (uint256 OHMRec) { if (bond) { // pull users fromToken uint256 toInvest = _pullTokens(fromToken, amountIn, affiliate, true); // swap fromToken -> toToken uint256 tokensBought = _fillQuote(fromToken, toToken, toInvest, swapTarget, swapData); require(tokensBought >= minToToken, "High Slippage"); // get depo address address depo = principalToDepository[toToken][bondPayoutToken]; require(depo != address(0), "Bond depo doesn't exist"); // deposit bond on behalf of user, and return OHMRec OHMRec = IBondDepository(depo).deposit(tokensBought, maxBondPrice, msg.sender); // emit zapIn emit zapIn(msg.sender, toToken, OHMRec, affiliate); } else { require(toToken == sOHM || toToken == wsOHM, "toToken must be sOHM or wsOHM"); uint256 toInvest = _pullTokens(fromToken, amountIn, affiliate, true); uint256 tokensBought = _fillQuote(fromToken, OHM, toInvest, swapTarget, swapData); OHMRec = _enterOlympus(tokensBought, toToken); require(OHMRec > minToToken, "High Slippage"); emit zapIn(msg.sender, sOHM, OHMRec, affiliate); } } /** * @notice This function withdraws assets from OlympusDAO, receiving tokens or ETH * @param fromToken The ibToken being withdrawn * @param amountIn The quantity of fromToken to withdraw * @param toToken Address of the token to receive (0 address if ETH) * @param minToTokens The minimum acceptable quantity of tokens to receive. Reverts otherwise * @param swapTarget Excecution target for the swap or zap * @param swapData DEX or Zap data * @param affiliate Affiliate address * @return tokensRec Quantity of aTokens received */ function ZapOut( address fromToken, uint256 amountIn, address toToken, uint256 minToTokens, address swapTarget, bytes calldata swapData, address affiliate ) external stopInEmergency returns (uint256 tokensRec) { require(fromToken == sOHM || fromToken == wsOHM, "fromToken must be sOHM or wsOHM"); amountIn = _pullTokens(fromToken, amountIn); uint256 OHMRec = _exitOlympus(fromToken, amountIn); tokensRec = _fillQuote(OHM, toToken, OHMRec, swapTarget, swapData); require(tokensRec >= minToTokens, "High Slippage"); uint256 totalGoodwillPortion; if (toToken == address(0)) { totalGoodwillPortion = _subtractGoodwill(ETHAddress, tokensRec, affiliate, true); payable(msg.sender).transfer(tokensRec - totalGoodwillPortion); } else { totalGoodwillPortion = _subtractGoodwill(toToken, tokensRec, affiliate, true); IERC20(toToken).safeTransfer(msg.sender, tokensRec - totalGoodwillPortion); } tokensRec = tokensRec - totalGoodwillPortion; emit zapOut(msg.sender, toToken, tokensRec, affiliate); } function _enterOlympus(uint256 amount, address toToken) internal returns (uint256) { _approveToken(OHM, staking, amount); if (toToken == wsOHM) { IStaking(staking).stake(amount, address(this)); IStaking(staking).claim(address(this)); _approveToken(sOHM, wsOHM, amount); uint256 beforeBalance = _getBalance(wsOHM); IwsOHM(wsOHM).wrap(amount); uint256 wsOHMRec = _getBalance(wsOHM) - beforeBalance; IERC20(wsOHM).safeTransfer(msg.sender, wsOHMRec); return wsOHMRec; } IStaking(staking).stake(amount, msg.sender); IStaking(staking).claim(msg.sender); return amount; } function _exitOlympus(address fromToken, uint256 amount) internal returns (uint256) { if (fromToken == wsOHM) { uint256 sOHMRec = IwsOHM(wsOHM).unwrap(amount); _approveToken(sOHM, address(staking), sOHMRec); IStaking(staking).unstake(sOHMRec, true); return sOHMRec; } _approveToken(sOHM, address(staking), amount); IStaking(staking).unstake(amount, true); return amount; } function removeLiquidityReturn(address fromToken, uint256 fromAmount) external view returns (uint256 ohmAmount) { if (fromToken == sOHM) { return fromAmount; } else if (fromToken == wsOHM) { return IwsOHM(wsOHM).wOHMTosOHM(fromAmount); } } ///////////// olympus only ///////////// function update_OlympusDAO(address _olympusDAO) external onlyOlympusDAO { olympusDAO = _olympusDAO; } function update_Staking(address _staking) external onlyOlympusDAO { staking = _staking; } function update_sOHM(address _sOHM) external onlyOlympusDAO { sOHM = _sOHM; } function update_wsOHM(address _wsOHM) external onlyOlympusDAO { wsOHM = _wsOHM; } function update_BondDepos( address[] calldata principals, address[] calldata payoutTokens, address[] calldata depos ) external onlyOlympusDAO { require( principals.length == depos.length && depos.length == payoutTokens.length, "array param lengths must match" ); // update depos for each principal for (uint256 i; i < principals.length; i++) { principalToDepository[principals[i]][payoutTokens[i]] = depos[i]; // max approve depo to save on gas _approveToken(principals[i], depos[i]); } } function bondPrice(address principal, address payoutToken) external view returns (uint256) { return IBondDepository(principalToDepository[principal][payoutToken]).bondPrice(); } }
// SPDX-License-Identifier: WTFPL pragma solidity ^0.8.0; interface IBondDepository { function deposit( uint256 _amount, uint256 _maxPrice, address _depositor ) external returns (uint256); function payoutFor(uint256 _value) external view returns (uint256); function bondPrice() external view returns (uint256 price_); function bondInfo(address _depositor) external view returns ( uint256 payout, uint256 vesting, uint256 lastBlock, uint256 pricePaid ); }
// SPDX-License-Identifier: WTFPL pragma solidity ^0.8.0; interface IStaking { function stake(uint256 _amount, address _recipient) external returns (bool); function unstake(uint256 _amount, bool _trigger) external; function claim(address _recipient) external; }
// SPDX-License-Identifier: WTFPL pragma solidity ^0.8.0; interface IwsOHM { function unwrap(uint256 _amount) external returns (uint256); function wrap(uint256 _amount) external returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function balanceOf(address account) external view returns (uint256); function wOHMTosOHM(uint256 _amount) external view returns (uint256); }
// SPDX-License-Identifier: WTFPL pragma solidity ^0.8.0; import "./IStaking.sol"; interface IOlympusZap { function update_Staking(IStaking _staking) external; function update_sOHM(address _sOHM) external; function update_wsOHM(address _wsOHM) external; function update_gOHM(address _gOHM) external; function update_BondDepository(address principal, address depository) external; }
// ███████╗░█████╗░██████╗░██████╗░███████╗██████╗░░░░███████╗██╗ // ╚════██║██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔══██╗░░░██╔════╝██║ // ░░███╔═╝███████║██████╔╝██████╔╝█████╗░░██████╔╝░░░█████╗░░██║ // ██╔══╝░░██╔══██║██╔═══╝░██╔═══╝░██╔══╝░░██╔══██╗░░░██╔══╝░░██║ // ███████╗██║░░██║██║░░░░░██║░░░░░███████╗██║░░██║██╗██║░░░░░██║ // ╚══════╝╚═╝░░╚═╝╚═╝░░░░░╚═╝░░░░░╚══════╝╚═╝░░╚═╝╚═╝╚═╝░░░░░╚═╝ // Copyright (C) 2021 zapper // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // /// @author Zapper and OlympusDAO /// @notice This contract enters Olympus Pro bonds // SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.0; import "./interfaces/ICustomBondDepo.sol"; import "./libraries/ZapBaseV2_2.sol"; contract OlympusPro_Zap_V1 is ZapBaseV2_2 { using SafeERC20 for IERC20; /////////////// Events /////////////// // Emitted when `sender` Zaps In event zapIn(address sender, address token, uint256 tokensRec, address affiliate); // Emitted when `sender` Zaps Out event zapOut(address sender, address token, uint256 tokensRec, address affiliate); /////////////// State /////////////// address public olympusDAO; // IE DAI => wanted payout token (IE OHM) => bond depo mapping(address => mapping(address => address)) public principalToDepository; // If a token can be paid out by Olympus Pro mapping(address => bool) public isOlympusProToken; /////////////// Modifiers /////////////// modifier onlyOlympusDAO() { require(msg.sender == olympusDAO, "Only OlympusDAO"); _; } /////////////// Construction /////////////// constructor( uint256 _goodwill, uint256 _affiliateSplit, address _olympusDAO ) ZapBaseV2_2(_goodwill, _affiliateSplit) { // 0x Proxy approvedTargets[0xDef1C0ded9bec7F1a1670819833240f027b25EfF] = true; // Zapper Sushiswap Zap In approvedTargets[0x5abfbE56553a5d794330EACCF556Ca1d2a55647C] = true; // Zapper Uniswap V2 Zap In approvedTargets[0x6D9893fa101CD2b1F8D1A12DE3189ff7b80FdC10] = true; olympusDAO = _olympusDAO; transferOwnership(ZapperAdmin); } /** * @notice This function deposits assets into OlympusDAO with ETH or ERC20 tokens * @param fromToken The token used for entry (address(0) if ether) * @param amountIn The amount of fromToken to invest * @param toToken The token fromToken is getting converted to. * @param minToToken The minimum acceptable quantity sOHM or wsOHM or principal tokens to receive. Reverts otherwise * @param swapTarget Excecution target for the swap or zap * @param swapData DEX or Zap data. Must swap to ibToken underlying address * @param affiliate Affiliate address * @param maxBondPrice Max price for a bond denominated in toToken/principal. Ignored if not bonding. * @return bondTokensRec quantity of sOHM or wsOHM received (depending on toToken) or the quantity OHM vesting (if bond is true) */ function ZapIn( address fromToken, uint256 amountIn, address toToken, uint256 minToToken, address swapTarget, bytes calldata swapData, address affiliate, address bondPayoutToken, uint256 maxBondPrice ) external payable stopInEmergency returns (uint256 bondTokensRec) { // make sure payout token is OP bondable token require(isOlympusProToken[bondPayoutToken], "fromToken must be bondable using OP"); // pull users fromToken uint256 toInvest = _pullTokens(fromToken, amountIn, affiliate, true); // swap fromToken -> toToken uint256 tokensBought = _fillQuote(fromToken, toToken, toInvest, swapTarget, swapData); require(tokensBought >= minToToken, "High Slippage"); // get depo address address depo = principalToDepository[toToken][bondPayoutToken]; require(depo != address(0), "Bond depo doesn't exist"); // deposit bond on behalf of user, and return bondTokensRec bondTokensRec = ICustomBondDepo(depo).deposit(tokensBought, maxBondPrice, msg.sender); // emit zapIn emit zapIn(msg.sender, toToken, bondTokensRec, affiliate); } ///////////// olympus only ///////////// function update_OlympusDAO(address _olympusDAO) external onlyOlympusDAO { olympusDAO = _olympusDAO; } string private ARRAY_LENGTH_ERROR = "array param lengths must match"; // save gas function update_isOlympusProToken(address[] memory _tokens, bool[] memory _isToken) external onlyOlympusDAO { require(_tokens.length == _isToken.length, ARRAY_LENGTH_ERROR); for (uint256 i; i < _tokens.length; i++) { isOlympusProToken[_tokens[i]] = _isToken[i]; } } function update_BondDepos( address[] calldata principals, address[] calldata payoutTokens, address[] calldata depos ) external onlyOlympusDAO { require( principals.length == depos.length && depos.length == payoutTokens.length, ARRAY_LENGTH_ERROR ); // update depos for each principal for (uint256 i; i < principals.length; i++) { require(isOlympusProToken[payoutTokens[i]], "payoutTokens must be on OP"); principalToDepository[principals[i]][payoutTokens[i]] = depos[i]; // max approve depo to save on gas _approveToken(principals[i], depos[i]); } } function bondPrice(address principal, address payoutToken) external view returns (uint256) { return ICustomBondDepo(principalToDepository[principal][payoutToken]).bondPrice(); } function payoutFor( address principal, address payoutToken, uint256 value ) external view returns (uint256) { return ICustomBondDepo(principalToDepository[principal][payoutToken]).payoutFor(value); } }
// SPDX-License-Identifier: GPL-2.0 pragma solidity ^0.8.0; interface ICustomBondDepo { function deposit( uint256 _amount, uint256 _maxPrice, address _depositor ) external returns (uint256); function bondPrice() external view returns (uint256); function payoutFor(uint256 _value) external view returns (uint256); }
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "metadata": { "useLiteralContent": true } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_depo","type":"address"},{"internalType":"address","name":"_staking","type":"address"},{"internalType":"address","name":"_OHM","type":"address"},{"internalType":"address","name":"_sOHM","type":"address"},{"internalType":"address","name":"_gOHM","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokensRec","type":"uint256"},{"indexed":false,"internalType":"address","name":"referral","type":"address"}],"name":"zapBond","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokensRec","type":"uint256"},{"indexed":false,"internalType":"address","name":"referral","type":"address"}],"name":"zapStake","type":"event"},{"inputs":[],"name":"OHM","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"fromToken","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"principal","type":"address"},{"internalType":"address","name":"swapTarget","type":"address"},{"internalType":"bytes","name":"swapData","type":"bytes"},{"internalType":"address","name":"referral","type":"address"},{"internalType":"uint256","name":"maxPrice","type":"uint256"},{"internalType":"uint256","name":"bondId","type":"uint256"}],"name":"ZapBond","outputs":[{"internalType":"uint256","name":"OHMRec","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"fromToken","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"toToken","type":"address"},{"internalType":"uint256","name":"minToToken","type":"uint256"},{"internalType":"address","name":"swapTarget","type":"address"},{"internalType":"bytes","name":"swapData","type":"bytes"},{"internalType":"address","name":"referral","type":"address"}],"name":"ZapStake","outputs":[{"internalType":"uint256","name":"OHMRec","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"affiliateBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"affiliates","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"affilliateWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedTargets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"feeWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gOHM","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"goodwill","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"sOHM","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"bool[]","name":"isApproved","type":"bool[]"}],"name":"setApprovedTargets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_affiliate","type":"address"},{"internalType":"bool","name":"_status","type":"bool"}],"name":"set_affiliate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"zapAddress","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"set_feeWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_new_affiliateSplit","type":"uint256"}],"name":"set_new_affiliateSplit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_new_goodwill","type":"uint256"}],"name":"set_new_goodwill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"staking","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stopped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleContractActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalAffiliateBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_depo","type":"address"}],"name":"update_Depo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_staking","type":"address"}],"name":"update_Staking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60e06040523480156200001157600080fd5b5060405162002aa838038062002aa883398101604081905262000034916200013d565b600080546001600160a01b031916339081178255604051829190819083907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35060029190915560035573def1c0ded9bec7f1a1670819833240f027b25eff60005260076020527ff6019cd1944dc466e824190b288e5a63528dd4c9a6d8cbd707956fd30d2f1e0d805460ff19166001179055600880546001600160a01b039687166001600160a01b03199182161790915560098054959096169416939093179093556001600160601b0319606091821b811660805292811b831660a0521b1660c052620001ac565b80516001600160a01b03811681146200013857600080fd5b919050565b600080600080600060a0868803121562000155578081fd5b620001608662000120565b9450620001706020870162000120565b9350620001806040870162000120565b9250620001906060870162000120565b9150620001a06080870162000120565b90509295509295909350565b60805160601c60a05160601c60c05160601c6128ae620001fa600039600081816102430152611c04015260006102c901526000818161052a0152818161124e0152611bd301526128ae6000f3fe6080604052600436106101b05760003560e01c80635de0398e116100ec578063a6c41fec1161008a578063e517e76411610064578063e517e7641461058f578063ef477482146105af578063f2fde38b146105c2578063fbec27bf146105e257600080fd5b8063a6c41fec14610518578063ce292acf1461054c578063d408f6571461055f57600080fd5b806375f12b21116100c657806375f12b21146104895780638da5cb5b146104aa5780639735a634146104c85780639779d1a6146104e857600080fd5b80635de0398e1461043e5780635ecb16cd14610454578063715018a61461047457600080fd5b806318b135e31161015957806345b3358c1161013357806345b3358c1461039e5780634cf088d9146103be5780634f51e294146103de578063550bfa561461041e57600080fd5b806318b135e31461033157806320740e9a1461035e5780633ff428c71461037e57600080fd5b80631385d24c1161018a5780631385d24c146102a257806315079925146102b75780631781261f146102eb57600080fd5b806301e980d4146102115780630cd30585146102315780630dc9de851461028257600080fd5b3661020c573332141561020a5760405162461bcd60e51b815260206004820152601860248201527f446f206e6f742073656e6420455448206469726563746c79000000000000000060448201526064015b60405180910390fd5b005b600080fd5b34801561021d57600080fd5b5061020a61022c3660046126bf565b610602565b34801561023d57600080fd5b506102657f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561028e57600080fd5b5061020a61029d3660046125de565b6106c6565b3480156102ae57600080fd5b5061020a610921565b3480156102c357600080fd5b506102657f000000000000000000000000000000000000000000000000000000000000000081565b3480156102f757600080fd5b5061032361030636600461243e565b600560209081526000928352604080842090915290825290205481565b604051908152602001610279565b34801561033d57600080fd5b5061032361034c366004612424565b60066020526000908152604090205481565b34801561036a57600080fd5b50600854610265906001600160a01b031681565b34801561038a57600080fd5b5061020a610399366004612470565b6109a5565b3480156103aa57600080fd5b5061020a6103b9366004612424565b610a18565b3480156103ca57600080fd5b50600954610265906001600160a01b031681565b3480156103ea57600080fd5b5061040e6103f9366004612424565b60046020526000908152604090205460ff1681565b6040519015158152602001610279565b34801561042a57600080fd5b5061020a6104393660046126bf565b610a8f565b34801561044a57600080fd5b5061032360025481565b34801561046057600080fd5b5061020a61046f3660046125de565b610b2d565b34801561048057600080fd5b5061020a610dbc565b34801561049557600080fd5b5060005461040e90600160a01b900460ff1681565b3480156104b657600080fd5b506000546001600160a01b0316610265565b3480156104d457600080fd5b5061020a6104e336600461261e565b610e5b565b3480156104f457600080fd5b5061040e610503366004612424565b60076020526000908152604090205460ff1681565b34801561052457600080fd5b506102657f000000000000000000000000000000000000000000000000000000000000000081565b61032361055a3660046124a6565b610fac565b34801561056b57600080fd5b5061040e61057a366004612424565b60016020526000908152604090205460ff1681565b34801561059b57600080fd5b5061020a6105aa366004612424565b61117a565b6103236105bd366004612547565b6111f1565b3480156105ce57600080fd5b5061020a6105dd366004612424565b611366565b3480156105ee57600080fd5b5061020a6105fd366004612470565b611492565b6000546001600160a01b0316331461064a5760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b60648111156106c15760405162461bcd60e51b815260206004820152602160248201527f416666696c696174652053706c69742056616c7565206e6f7420616c6c6f776560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610201565b600355565b6000805b8281101561091b573360009081526005602052604081209085858481811061070257634e487b7160e01b600052603260045260246000fd5b90506020020160208101906107179190612424565b6001600160a01b0316815260208082019290925260409081016000908120543382526005909352908120919350908186868581811061076657634e487b7160e01b600052603260045260246000fd5b905060200201602081019061077b9190612424565b6001600160a01b03166001600160a01b031681526020019081526020016000208190555081600660008686858181106107c457634e487b7160e01b600052603260045260246000fd5b90506020020160208101906107d99190612424565b6001600160a01b03166001600160a01b031681526020019081526020016000205461080491906127d3565b6006600086868581811061082857634e487b7160e01b600052603260045260246000fd5b905060200201602081019061083d9190612424565b6001600160a01b0316815260208101919091526040016000205573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84848381811061088c57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906108a19190612424565b6001600160a01b031614156108bf576108ba3383611505565b610909565b61090933838686858181106108e457634e487b7160e01b600052603260045260246000fd5b90506020020160208101906108f99190612424565b6001600160a01b0316919061161e565b8061091381612816565b9150506106ca565b50505050565b6000546001600160a01b031633146109695760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8116600160a01b9182900460ff1615909102179055565b6000546001600160a01b031633146109ed5760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b6001600160a01b03919091166000908152600460205260409020805460ff1916911515919091179055565b6000546001600160a01b03163314610a605760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b6008805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610ad75760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b6064811115610b285760405162461bcd60e51b815260206004820152601a60248201527f476f6f6457696c6c2056616c7565206e6f7420616c6c6f7765640000000000006044820152606401610201565b600255565b6000546001600160a01b03163314610b755760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b60005b81811015610db757600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee848484818110610bb757634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610bcc9190612424565b6001600160a01b03161415610c5a5760066000858585818110610bff57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610c149190612424565b6001600160a01b03168152602081019190915260400160002054610c3890476127d3565b9050610c55610c4f6000546001600160a01b031690565b82611505565b610da4565b60066000858585818110610c7e57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610c939190612424565b6001600160a01b03166001600160a01b0316815260200190815260200160002054848484818110610cd457634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610ce99190612424565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015610d2a57600080fd5b505afa158015610d3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6291906126d7565b610d6c91906127d3565b9050610da4610d836000546001600160a01b031690565b828686868181106108e457634e487b7160e01b600052603260045260246000fd5b5080610daf81612816565b915050610b78565b505050565b6000546001600160a01b03163314610e045760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b6000546001600160a01b03163314610ea35760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b828114610ef25760405162461bcd60e51b815260206004820152601460248201527f496e76616c696420496e707574206c656e6774680000000000000000000000006044820152606401610201565b60005b83811015610fa557828282818110610f1d57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610f329190612687565b60076000878785818110610f5657634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610f6b9190612424565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905580610f9d81612816565b915050610ef5565b5050505050565b60008054600160a01b900460ff1615610ff05760405162461bcd60e51b815260206004820152600660248201526514185d5cd95960d21b6044820152606401610201565b6000610fff8b8b8760016116c7565b905060006110468c8b848c8c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061183392505050565b600854909150611061908b906001600160a01b031683611b75565b6008546040517f7c770aae0000000000000000000000000000000000000000000000000000000081526004810186905260248101839052604481018790523360648201526001600160a01b03888116608483015290911690637c770aae9060a401606060405180830381600087803b1580156110dc57600080fd5b505af11580156110f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111491906126ef565b5050604080513381526001600160a01b03808e16602083015291810183905290881660608201529093507f7ec3a67ed5aa3b5893b0a5fa562eb9f755a07e23e2602f330b18b7b8a81cd0c69060800160405180910390a150509998505050505050505050565b6000546001600160a01b031633146111c25760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b6009805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60008054600160a01b900460ff16156112355760405162461bcd60e51b815260206004820152600660248201526514185d5cd95960d21b6044820152606401610201565b60006112448a8a8560016116c7565b905060006112ab8b7f0000000000000000000000000000000000000000000000000000000000000000848a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061183392505050565b90506112b7818a611bc5565b92508783116113085760405162461bcd60e51b815260206004820152600d60248201527f4869676820536c697070616765000000000000000000000000000000000000006044820152606401610201565b604080513381526001600160a01b038b811660208301528183018690528616606082015290517f4a44abc58b2b53c726aeffc2dfee3b5ea1ba2132ca606a1d7e0994ccd625da279181900360800190a1505098975050505050505050565b6000546001600160a01b031633146113ae5760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b6001600160a01b03811661142a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610201565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000546001600160a01b031633146114da5760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b6001600160a01b03919091166000908152600160205260409020805460ff1916911515919091179055565b804710156115555760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610201565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146115a2576040519150601f19603f3d011682016040523d82523d6000602084013e6115a7565b606091505b5050905080610db75760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610201565b6040516001600160a01b038316602482015260448101829052610db79084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611d9c565b6000806001600160a01b03861661175c57600034116117285760405162461bcd60e51b815260206004820152600b60248201527f4e6f204554482073656e740000000000000000000000000000000000000000006044820152606401610201565b61174873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee348686611e81565b905061175481346127d3565b91505061182b565b600085116117ac5760405162461bcd60e51b815260206004820152601460248201527f496e76616c696420746f6b656e20616d6f756e740000000000000000000000006044820152606401610201565b34156117fa5760405162461bcd60e51b815260206004820152601360248201527f4554482073656e74207769746820746f6b656e000000000000000000000000006044820152606401610201565b61180f6001600160a01b038716333088611fae565b61181b86868686611e81565b905061182781866127d3565b9150505b949350505050565b6000846001600160a01b0316866001600160a01b03161415611856575082611b6c565b6001600160a01b03861615801561188957506001600160a01b03851673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b156118fe5773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b1580156118dd57600080fd5b505af11580156118f1573d6000803e3d6000fd5b5050505050839050611b6c565b6001600160a01b03861673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc214801561193157506001600160a01b038516155b156119bc576040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810185905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d90602401600060405180830381600087803b15801561199c57600080fd5b505af11580156119b0573d6000803e3d6000fd5b50505050839050611b6c565b60006001600160a01b0387166119d35750836119de565b6119de878587611b75565b60006119e987611fff565b6001600160a01b03861660009081526007602052604090205490915060ff16611a545760405162461bcd60e51b815260206004820152601560248201527f546172676574206e6f7420417574686f72697a656400000000000000000000006044820152606401610201565b6000856001600160a01b03168386604051611a6f919061272d565b60006040518083038185875af1925050503d8060008114611aac576040519150601f19603f3d011682016040523d82523d6000602084013e611ab1565b606091505b5050905080611b025760405162461bcd60e51b815260206004820152601560248201527f4572726f72205377617070696e6720546f6b656e7300000000000000000000006044820152606401610201565b81611b0c89611fff565b611b1691906127d3565b935060008411611b685760405162461bcd60e51b815260206004820152601860248201527f5377617070656420546f20496e76616c696420546f6b656e00000000000000006044820152606401610201565b5050505b95945050505050565b6001600160a01b0383161580611b9257506001600160a01b038216155b15611b9c57505050565b611bb16001600160a01b038416836000612095565b610db76001600160a01b0384168383612095565b6009546000908190611c02907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b031686611b75565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03161415611ceb57600954604051631b0cd93b60e31b81523060048201526024810186905260006044820152600160648201526001600160a01b039091169063d866c9d890608401602060405180830381600087803b158015611c9657600080fd5b505af1158015611caa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cce91906126d7565b9050611ce46001600160a01b038416338361161e565b9050611d96565b600954604051631b0cd93b60e31b81523060048201526024810186905260016044820181905260648201526001600160a01b039091169063d866c9d890608401602060405180830381600087803b158015611d4557600080fd5b505af1158015611d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7d91906126d7565b9050611d936001600160a01b038416338361161e565b90505b92915050565b6000611df1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166121f29092919063ffffffff16565b805190915015610db75780806020019051810190611e0f91906126a3565b610db75760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610201565b3360009081526001602052604081205460025460ff9091169015801590611ea55750825b8015611eaf575080155b15611fa55761271060025486611ec591906127b4565b611ecf9190612794565b6001600160a01b03851660009081526004602052604090205490925060ff1615611fa5576001600160a01b038616611f195773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee95505b6000606460035484611f2b91906127b4565b611f359190612794565b6001600160a01b038087166000908152600560209081526040808320938c16835292905290812080549293508392909190611f7190849061277c565b90915550506001600160a01b03871660009081526006602052604081208054839290611f9e90849061277c565b9091555050505b50949350505050565b6040516001600160a01b038085166024830152831660448201526064810182905261091b9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611663565b60006001600160a01b038216612016575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a082319060240160206040518083038186803b15801561205557600080fd5b505afa158015612069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061208d91906126d7565b90505b919050565b80158061213757506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156120fd57600080fd5b505afa158015612111573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061213591906126d7565b155b6121a95760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610201565b6040516001600160a01b038316602482015260448101829052610db79084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611663565b6060612201848460008561220b565b90505b9392505050565b6060824710156122835760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610201565b843b6122d15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610201565b600080866001600160a01b031685876040516122ed919061272d565b60006040518083038185875af1925050503d806000811461232a576040519150601f19603f3d011682016040523d82523d6000602084013e61232f565b606091505b509150915061233f82828661234a565b979650505050505050565b60608315612359575081612204565b8251156123695782518084602001fd5b8160405162461bcd60e51b81526004016102019190612749565b80356001600160a01b038116811461209057600080fd5b60008083601f8401126123ab578182fd5b50813567ffffffffffffffff8111156123c2578182fd5b6020830191508360208260051b85010111156123dd57600080fd5b9250929050565b60008083601f8401126123f5578182fd5b50813567ffffffffffffffff81111561240c578182fd5b6020830191508360208285010111156123dd57600080fd5b600060208284031215612435578081fd5b61220482612383565b60008060408385031215612450578081fd5b61245983612383565b915061246760208401612383565b90509250929050565b60008060408385031215612482578182fd5b61248b83612383565b9150602083013561249b81612847565b809150509250929050565b60008060008060008060008060006101008a8c0312156124c4578485fd5b6124cd8a612383565b985060208a013597506124e260408b01612383565b96506124f060608b01612383565b955060808a013567ffffffffffffffff81111561250b578586fd5b6125178c828d016123e4565b909650945061252a905060a08b01612383565b925060c08a0135915060e08a013590509295985092959850929598565b60008060008060008060008060e0898b031215612562578384fd5b61256b89612383565b97506020890135965061258060408a01612383565b95506060890135945061259560808a01612383565b935060a089013567ffffffffffffffff8111156125b0578384fd5b6125bc8b828c016123e4565b90945092506125cf905060c08a01612383565b90509295985092959890939650565b600080602083850312156125f0578182fd5b823567ffffffffffffffff811115612606578283fd5b6126128582860161239a565b90969095509350505050565b60008060008060408587031215612633578384fd5b843567ffffffffffffffff8082111561264a578586fd5b6126568883890161239a565b9096509450602087013591508082111561266e578384fd5b5061267b8782880161239a565b95989497509550505050565b600060208284031215612698578081fd5b8135611d9381612847565b6000602082840312156126b4578081fd5b8151611d9381612847565b6000602082840312156126d0578081fd5b5035919050565b6000602082840312156126e8578081fd5b5051919050565b600080600060608486031215612703578081fd5b8351925060208401519150604084015161ffff81168114612722578182fd5b809150509250925092565b6000825161273f8184602087016127ea565b9190910192915050565b60208152600082518060208401526127688160408501602087016127ea565b601f01601f19169190910160400192915050565b6000821982111561278f5761278f612831565b500190565b6000826127af57634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156127ce576127ce612831565b500290565b6000828210156127e5576127e5612831565b500390565b60005b838110156128055781810151838201526020016127ed565b8381111561091b5750506000910152565b600060001982141561282a5761282a612831565b5060010190565b634e487b7160e01b600052601160045260246000fd5b801515811461285557600080fd5b5056fe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a264697066735822122091222a19ea774491eec7467aa9a8d141266aef109ac42b1c8f4ebb95e7f4bdb264736f6c634300080400330000000000000000000000009025046c6fb25fb39e720d97a8fd881ed69a1ef6000000000000000000000000b63cac384247597756545b500253ff8e607a802000000000000000000000000064aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d500000000000000000000000004906695d6d12cf5459975d7c3c03356e4ccd4600000000000000000000000000ab87046fbb341d058f17cbc4c1133f25a20a52f
Deployed Bytecode
0x6080604052600436106101b05760003560e01c80635de0398e116100ec578063a6c41fec1161008a578063e517e76411610064578063e517e7641461058f578063ef477482146105af578063f2fde38b146105c2578063fbec27bf146105e257600080fd5b8063a6c41fec14610518578063ce292acf1461054c578063d408f6571461055f57600080fd5b806375f12b21116100c657806375f12b21146104895780638da5cb5b146104aa5780639735a634146104c85780639779d1a6146104e857600080fd5b80635de0398e1461043e5780635ecb16cd14610454578063715018a61461047457600080fd5b806318b135e31161015957806345b3358c1161013357806345b3358c1461039e5780634cf088d9146103be5780634f51e294146103de578063550bfa561461041e57600080fd5b806318b135e31461033157806320740e9a1461035e5780633ff428c71461037e57600080fd5b80631385d24c1161018a5780631385d24c146102a257806315079925146102b75780631781261f146102eb57600080fd5b806301e980d4146102115780630cd30585146102315780630dc9de851461028257600080fd5b3661020c573332141561020a5760405162461bcd60e51b815260206004820152601860248201527f446f206e6f742073656e6420455448206469726563746c79000000000000000060448201526064015b60405180910390fd5b005b600080fd5b34801561021d57600080fd5b5061020a61022c3660046126bf565b610602565b34801561023d57600080fd5b506102657f0000000000000000000000000ab87046fbb341d058f17cbc4c1133f25a20a52f81565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561028e57600080fd5b5061020a61029d3660046125de565b6106c6565b3480156102ae57600080fd5b5061020a610921565b3480156102c357600080fd5b506102657f00000000000000000000000004906695d6d12cf5459975d7c3c03356e4ccd46081565b3480156102f757600080fd5b5061032361030636600461243e565b600560209081526000928352604080842090915290825290205481565b604051908152602001610279565b34801561033d57600080fd5b5061032361034c366004612424565b60066020526000908152604090205481565b34801561036a57600080fd5b50600854610265906001600160a01b031681565b34801561038a57600080fd5b5061020a610399366004612470565b6109a5565b3480156103aa57600080fd5b5061020a6103b9366004612424565b610a18565b3480156103ca57600080fd5b50600954610265906001600160a01b031681565b3480156103ea57600080fd5b5061040e6103f9366004612424565b60046020526000908152604090205460ff1681565b6040519015158152602001610279565b34801561042a57600080fd5b5061020a6104393660046126bf565b610a8f565b34801561044a57600080fd5b5061032360025481565b34801561046057600080fd5b5061020a61046f3660046125de565b610b2d565b34801561048057600080fd5b5061020a610dbc565b34801561049557600080fd5b5060005461040e90600160a01b900460ff1681565b3480156104b657600080fd5b506000546001600160a01b0316610265565b3480156104d457600080fd5b5061020a6104e336600461261e565b610e5b565b3480156104f457600080fd5b5061040e610503366004612424565b60076020526000908152604090205460ff1681565b34801561052457600080fd5b506102657f00000000000000000000000064aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d581565b61032361055a3660046124a6565b610fac565b34801561056b57600080fd5b5061040e61057a366004612424565b60016020526000908152604090205460ff1681565b34801561059b57600080fd5b5061020a6105aa366004612424565b61117a565b6103236105bd366004612547565b6111f1565b3480156105ce57600080fd5b5061020a6105dd366004612424565b611366565b3480156105ee57600080fd5b5061020a6105fd366004612470565b611492565b6000546001600160a01b0316331461064a5760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b60648111156106c15760405162461bcd60e51b815260206004820152602160248201527f416666696c696174652053706c69742056616c7565206e6f7420616c6c6f776560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610201565b600355565b6000805b8281101561091b573360009081526005602052604081209085858481811061070257634e487b7160e01b600052603260045260246000fd5b90506020020160208101906107179190612424565b6001600160a01b0316815260208082019290925260409081016000908120543382526005909352908120919350908186868581811061076657634e487b7160e01b600052603260045260246000fd5b905060200201602081019061077b9190612424565b6001600160a01b03166001600160a01b031681526020019081526020016000208190555081600660008686858181106107c457634e487b7160e01b600052603260045260246000fd5b90506020020160208101906107d99190612424565b6001600160a01b03166001600160a01b031681526020019081526020016000205461080491906127d3565b6006600086868581811061082857634e487b7160e01b600052603260045260246000fd5b905060200201602081019061083d9190612424565b6001600160a01b0316815260208101919091526040016000205573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84848381811061088c57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906108a19190612424565b6001600160a01b031614156108bf576108ba3383611505565b610909565b61090933838686858181106108e457634e487b7160e01b600052603260045260246000fd5b90506020020160208101906108f99190612424565b6001600160a01b0316919061161e565b8061091381612816565b9150506106ca565b50505050565b6000546001600160a01b031633146109695760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8116600160a01b9182900460ff1615909102179055565b6000546001600160a01b031633146109ed5760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b6001600160a01b03919091166000908152600460205260409020805460ff1916911515919091179055565b6000546001600160a01b03163314610a605760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b6008805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610ad75760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b6064811115610b285760405162461bcd60e51b815260206004820152601a60248201527f476f6f6457696c6c2056616c7565206e6f7420616c6c6f7765640000000000006044820152606401610201565b600255565b6000546001600160a01b03163314610b755760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b60005b81811015610db757600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee848484818110610bb757634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610bcc9190612424565b6001600160a01b03161415610c5a5760066000858585818110610bff57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610c149190612424565b6001600160a01b03168152602081019190915260400160002054610c3890476127d3565b9050610c55610c4f6000546001600160a01b031690565b82611505565b610da4565b60066000858585818110610c7e57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610c939190612424565b6001600160a01b03166001600160a01b0316815260200190815260200160002054848484818110610cd457634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610ce99190612424565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015610d2a57600080fd5b505afa158015610d3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6291906126d7565b610d6c91906127d3565b9050610da4610d836000546001600160a01b031690565b828686868181106108e457634e487b7160e01b600052603260045260246000fd5b5080610daf81612816565b915050610b78565b505050565b6000546001600160a01b03163314610e045760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b6000546001600160a01b03163314610ea35760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b828114610ef25760405162461bcd60e51b815260206004820152601460248201527f496e76616c696420496e707574206c656e6774680000000000000000000000006044820152606401610201565b60005b83811015610fa557828282818110610f1d57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610f329190612687565b60076000878785818110610f5657634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610f6b9190612424565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905580610f9d81612816565b915050610ef5565b5050505050565b60008054600160a01b900460ff1615610ff05760405162461bcd60e51b815260206004820152600660248201526514185d5cd95960d21b6044820152606401610201565b6000610fff8b8b8760016116c7565b905060006110468c8b848c8c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061183392505050565b600854909150611061908b906001600160a01b031683611b75565b6008546040517f7c770aae0000000000000000000000000000000000000000000000000000000081526004810186905260248101839052604481018790523360648201526001600160a01b03888116608483015290911690637c770aae9060a401606060405180830381600087803b1580156110dc57600080fd5b505af11580156110f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111491906126ef565b5050604080513381526001600160a01b03808e16602083015291810183905290881660608201529093507f7ec3a67ed5aa3b5893b0a5fa562eb9f755a07e23e2602f330b18b7b8a81cd0c69060800160405180910390a150509998505050505050505050565b6000546001600160a01b031633146111c25760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b6009805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60008054600160a01b900460ff16156112355760405162461bcd60e51b815260206004820152600660248201526514185d5cd95960d21b6044820152606401610201565b60006112448a8a8560016116c7565b905060006112ab8b7f00000000000000000000000064aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5848a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061183392505050565b90506112b7818a611bc5565b92508783116113085760405162461bcd60e51b815260206004820152600d60248201527f4869676820536c697070616765000000000000000000000000000000000000006044820152606401610201565b604080513381526001600160a01b038b811660208301528183018690528616606082015290517f4a44abc58b2b53c726aeffc2dfee3b5ea1ba2132ca606a1d7e0994ccd625da279181900360800190a1505098975050505050505050565b6000546001600160a01b031633146113ae5760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b6001600160a01b03811661142a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610201565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000546001600160a01b031633146114da5760405162461bcd60e51b815260206004820181905260248201526000805160206128598339815191526044820152606401610201565b6001600160a01b03919091166000908152600160205260409020805460ff1916911515919091179055565b804710156115555760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610201565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146115a2576040519150601f19603f3d011682016040523d82523d6000602084013e6115a7565b606091505b5050905080610db75760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610201565b6040516001600160a01b038316602482015260448101829052610db79084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611d9c565b6000806001600160a01b03861661175c57600034116117285760405162461bcd60e51b815260206004820152600b60248201527f4e6f204554482073656e740000000000000000000000000000000000000000006044820152606401610201565b61174873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee348686611e81565b905061175481346127d3565b91505061182b565b600085116117ac5760405162461bcd60e51b815260206004820152601460248201527f496e76616c696420746f6b656e20616d6f756e740000000000000000000000006044820152606401610201565b34156117fa5760405162461bcd60e51b815260206004820152601360248201527f4554482073656e74207769746820746f6b656e000000000000000000000000006044820152606401610201565b61180f6001600160a01b038716333088611fae565b61181b86868686611e81565b905061182781866127d3565b9150505b949350505050565b6000846001600160a01b0316866001600160a01b03161415611856575082611b6c565b6001600160a01b03861615801561188957506001600160a01b03851673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b156118fe5773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b1580156118dd57600080fd5b505af11580156118f1573d6000803e3d6000fd5b5050505050839050611b6c565b6001600160a01b03861673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc214801561193157506001600160a01b038516155b156119bc576040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810185905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d90602401600060405180830381600087803b15801561199c57600080fd5b505af11580156119b0573d6000803e3d6000fd5b50505050839050611b6c565b60006001600160a01b0387166119d35750836119de565b6119de878587611b75565b60006119e987611fff565b6001600160a01b03861660009081526007602052604090205490915060ff16611a545760405162461bcd60e51b815260206004820152601560248201527f546172676574206e6f7420417574686f72697a656400000000000000000000006044820152606401610201565b6000856001600160a01b03168386604051611a6f919061272d565b60006040518083038185875af1925050503d8060008114611aac576040519150601f19603f3d011682016040523d82523d6000602084013e611ab1565b606091505b5050905080611b025760405162461bcd60e51b815260206004820152601560248201527f4572726f72205377617070696e6720546f6b656e7300000000000000000000006044820152606401610201565b81611b0c89611fff565b611b1691906127d3565b935060008411611b685760405162461bcd60e51b815260206004820152601860248201527f5377617070656420546f20496e76616c696420546f6b656e00000000000000006044820152606401610201565b5050505b95945050505050565b6001600160a01b0383161580611b9257506001600160a01b038216155b15611b9c57505050565b611bb16001600160a01b038416836000612095565b610db76001600160a01b0384168383612095565b6009546000908190611c02907f00000000000000000000000064aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5906001600160a01b031686611b75565b7f0000000000000000000000000ab87046fbb341d058f17cbc4c1133f25a20a52f6001600160a01b0316836001600160a01b03161415611ceb57600954604051631b0cd93b60e31b81523060048201526024810186905260006044820152600160648201526001600160a01b039091169063d866c9d890608401602060405180830381600087803b158015611c9657600080fd5b505af1158015611caa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cce91906126d7565b9050611ce46001600160a01b038416338361161e565b9050611d96565b600954604051631b0cd93b60e31b81523060048201526024810186905260016044820181905260648201526001600160a01b039091169063d866c9d890608401602060405180830381600087803b158015611d4557600080fd5b505af1158015611d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7d91906126d7565b9050611d936001600160a01b038416338361161e565b90505b92915050565b6000611df1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166121f29092919063ffffffff16565b805190915015610db75780806020019051810190611e0f91906126a3565b610db75760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610201565b3360009081526001602052604081205460025460ff9091169015801590611ea55750825b8015611eaf575080155b15611fa55761271060025486611ec591906127b4565b611ecf9190612794565b6001600160a01b03851660009081526004602052604090205490925060ff1615611fa5576001600160a01b038616611f195773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee95505b6000606460035484611f2b91906127b4565b611f359190612794565b6001600160a01b038087166000908152600560209081526040808320938c16835292905290812080549293508392909190611f7190849061277c565b90915550506001600160a01b03871660009081526006602052604081208054839290611f9e90849061277c565b9091555050505b50949350505050565b6040516001600160a01b038085166024830152831660448201526064810182905261091b9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611663565b60006001600160a01b038216612016575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a082319060240160206040518083038186803b15801561205557600080fd5b505afa158015612069573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061208d91906126d7565b90505b919050565b80158061213757506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156120fd57600080fd5b505afa158015612111573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061213591906126d7565b155b6121a95760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610201565b6040516001600160a01b038316602482015260448101829052610db79084907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611663565b6060612201848460008561220b565b90505b9392505050565b6060824710156122835760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610201565b843b6122d15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610201565b600080866001600160a01b031685876040516122ed919061272d565b60006040518083038185875af1925050503d806000811461232a576040519150601f19603f3d011682016040523d82523d6000602084013e61232f565b606091505b509150915061233f82828661234a565b979650505050505050565b60608315612359575081612204565b8251156123695782518084602001fd5b8160405162461bcd60e51b81526004016102019190612749565b80356001600160a01b038116811461209057600080fd5b60008083601f8401126123ab578182fd5b50813567ffffffffffffffff8111156123c2578182fd5b6020830191508360208260051b85010111156123dd57600080fd5b9250929050565b60008083601f8401126123f5578182fd5b50813567ffffffffffffffff81111561240c578182fd5b6020830191508360208285010111156123dd57600080fd5b600060208284031215612435578081fd5b61220482612383565b60008060408385031215612450578081fd5b61245983612383565b915061246760208401612383565b90509250929050565b60008060408385031215612482578182fd5b61248b83612383565b9150602083013561249b81612847565b809150509250929050565b60008060008060008060008060006101008a8c0312156124c4578485fd5b6124cd8a612383565b985060208a013597506124e260408b01612383565b96506124f060608b01612383565b955060808a013567ffffffffffffffff81111561250b578586fd5b6125178c828d016123e4565b909650945061252a905060a08b01612383565b925060c08a0135915060e08a013590509295985092959850929598565b60008060008060008060008060e0898b031215612562578384fd5b61256b89612383565b97506020890135965061258060408a01612383565b95506060890135945061259560808a01612383565b935060a089013567ffffffffffffffff8111156125b0578384fd5b6125bc8b828c016123e4565b90945092506125cf905060c08a01612383565b90509295985092959890939650565b600080602083850312156125f0578182fd5b823567ffffffffffffffff811115612606578283fd5b6126128582860161239a565b90969095509350505050565b60008060008060408587031215612633578384fd5b843567ffffffffffffffff8082111561264a578586fd5b6126568883890161239a565b9096509450602087013591508082111561266e578384fd5b5061267b8782880161239a565b95989497509550505050565b600060208284031215612698578081fd5b8135611d9381612847565b6000602082840312156126b4578081fd5b8151611d9381612847565b6000602082840312156126d0578081fd5b5035919050565b6000602082840312156126e8578081fd5b5051919050565b600080600060608486031215612703578081fd5b8351925060208401519150604084015161ffff81168114612722578182fd5b809150509250925092565b6000825161273f8184602087016127ea565b9190910192915050565b60208152600082518060208401526127688160408501602087016127ea565b601f01601f19169190910160400192915050565b6000821982111561278f5761278f612831565b500190565b6000826127af57634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156127ce576127ce612831565b500290565b6000828210156127e5576127e5612831565b500390565b60005b838110156128055781810151838201526020016127ed565b8381111561091b5750506000910152565b600060001982141561282a5761282a612831565b5060010190565b634e487b7160e01b600052601160045260246000fd5b801515811461285557600080fd5b5056fe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a264697066735822122091222a19ea774491eec7467aa9a8d141266aef109ac42b1c8f4ebb95e7f4bdb264736f6c63430008040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009025046c6fb25fb39e720d97a8fd881ed69a1ef6000000000000000000000000b63cac384247597756545b500253ff8e607a802000000000000000000000000064aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d500000000000000000000000004906695d6d12cf5459975d7c3c03356e4ccd4600000000000000000000000000ab87046fbb341d058f17cbc4c1133f25a20a52f
-----Decoded View---------------
Arg [0] : _depo (address): 0x9025046c6fb25Fb39e720d97a8FD881ED69a1Ef6
Arg [1] : _staking (address): 0xB63cac384247597756545b500253ff8E607a8020
Arg [2] : _OHM (address): 0x64aa3364F17a4D01c6f1751Fd97C2BD3D7e7f1D5
Arg [3] : _sOHM (address): 0x04906695D6D12CF5459975d7C3C03356E4Ccd460
Arg [4] : _gOHM (address): 0x0ab87046fBb341D058F17CBC4c1133F25a20a52f
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000009025046c6fb25fb39e720d97a8fd881ed69a1ef6
Arg [1] : 000000000000000000000000b63cac384247597756545b500253ff8e607a8020
Arg [2] : 00000000000000000000000064aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5
Arg [3] : 00000000000000000000000004906695d6d12cf5459975d7c3c03356e4ccd460
Arg [4] : 0000000000000000000000000ab87046fbb341d058f17cbc4c1133f25a20a52f
Deployed Bytecode Sourcemap
411:5515:3:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14347:10:20;14361:9;14347:23;;14339:60;;;;-1:-1:-1;;;14339:60:20;;10382:2:21;14339:60:20;;;10364:21:21;10421:2;10401:18;;;10394:30;10460:26;10440:18;;;10433:54;10504:18;;14339:60:20;;;;;;;;;411:5515:3;;;;;10464:215:20;;;;;;;;;;-1:-1:-1;10464:215:20;;;;;:::i;:::-;;:::i;683:29:3:-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;6863:55:21;;;6845:74;;6833:2;6818:18;683:29:3;;;;;;;;11845:589:20;;;;;;;;;;-1:-1:-1;11845:589:20;;;;;:::i;:::-;;:::i;14212:84::-;;;;;;;;;;;;;:::i;647:29:3:-;;;;;;;;;;;;;;;4375:71:20;;;;;;;;;;-1:-1:-1;4375:71:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;17019:25:21;;;17007:2;16992:18;4375:71:20;16974:76:21;4475:56:20;;;;;;;;;;-1:-1:-1;4475:56:20;;;;;:::i;:::-;;;;;;;;;;;;;;557:19:3;;;;;;;;;;-1:-1:-1;557:19:3;;;;-1:-1:-1;;;;;557:19:3;;;10841:125:20;;;;;;;;;;-1:-1:-1;10841:125:20;;;;;:::i;:::-;;:::i;5840:84:3:-;;;;;;;;;;-1:-1:-1;5840:84:3;;;;;:::i;:::-;;:::i;583:22::-;;;;;;;;;;-1:-1:-1;583:22:3;;;;-1:-1:-1;;;;;583:22:3;;;4291:42:20;;;;;;;;;;-1:-1:-1;4291:42:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;9081:14:21;;9074:22;9056:41;;9044:2;9029:18;4291:42:20;9011:92:21;10084:198:20;;;;;;;;;;-1:-1:-1;10084:198:20;;;;;:::i;:::-;;:::i;4170:23::-;;;;;;;;;;;;;;;;11130:547;;;;;;;;;;-1:-1:-1;11130:547:20;;;;;:::i;:::-;;:::i;3344:145::-;;;;;;;;;;;;;:::i;3959:19::-;;;;;;;;;;-1:-1:-1;3959:19:20;;;;-1:-1:-1;;;3959:19:20;;;;;;2712:85;;;;;;;;;;-1:-1:-1;2758:7:20;2784:6;-1:-1:-1;;;;;2784:6:20;2712:85;;12625:331;;;;;;;;;;-1:-1:-1;12625:331:20;;;;;:::i;:::-;;:::i;4574:47::-;;;;;;;;;;-1:-1:-1;4574:47:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;612:28:3;;;;;;;;;;;;;;;3604:1042;;;;;;:::i;:::-;;:::i;4119:44:20:-;;;;;;;;;;-1:-1:-1;4119:44:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;5700:96:3;;;;;;;;;;-1:-1:-1;5700:96:3;;;;;:::i;:::-;;:::i;2235:741::-;;;;;;:::i;:::-;;:::i;3638:240:20:-;;;;;;;;;;-1:-1:-1;3638:240:20;;;;;:::i;:::-;;:::i;9836:128::-;;;;;;;;;;-1:-1:-1;9836:128:20;;;;;:::i;:::-;;:::i;10464:215::-;2758:7;2784:6;-1:-1:-1;;;;;2784:6:20;170:10:17;2924:23:20;2916:68;;;;-1:-1:-1;;;2916:68:20;;15522:2:21;2916:68:20;;;15504:21:21;;;15541:18;;;15534:30;-1:-1:-1;;;;;;;;;;;15580:18:21;;;15573:62;15652:18;;2916:68:20;15494:182:21;2916:68:20;10585:3:::1;10562:19;:26;;10554:72;;;::::0;-1:-1:-1;;;10554:72:20;;14780:2:21;10554:72:20::1;::::0;::::1;14762:21:21::0;14819:2;14799:18;;;14792:30;14858:34;14838:18;;;14831:62;14929:3;14909:18;;;14902:31;14950:19;;10554:72:20::1;14752:223:21::0;10554:72:20::1;10636:14;:36:::0;10464:215::o;11845:589::-;11919:16;;11945:483;11965:17;;;11945:483;;;12031:10;12014:28;;;;:16;:28;;;;;;12043:6;;12050:1;12043:9;;;;;-1:-1:-1;;;12043:9:20;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;12014:39:20;;;;;;;;;;;;;;;-1:-1:-1;12014:39:20;;;;12084:10;12067:28;;:16;:28;;;;;;12014:39;;-1:-1:-1;;;12096:6:20;;12103:1;12096:9;;;;;-1:-1:-1;;;12096:9:20;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;12067:39:20;-1:-1:-1;;;;;12067:39:20;;;;;;;;;;;;:43;;;;12194:8;12159:21;:32;12181:6;;12188:1;12181:9;;;;;-1:-1:-1;;;12181:9:20;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;12159:32:20;-1:-1:-1;;;;;12159:32:20;;;;;;;;;;;;;:43;;;;:::i;:::-;12124:21;:32;12146:6;;12153:1;12146:9;;;;;-1:-1:-1;;;12146:9:20;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;12124:32:20;;;;;;;;;;;;-1:-1:-1;12124:32:20;:78;4667:42;12221:6;;12228:1;12221:9;;;;;-1:-1:-1;;;12221:9:20;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;12221:23:20;;12217:201;;;12264:48;12290:10;12303:8;12264:17;:48::i;:::-;12217:201;;;12351:52;12382:10;12394:8;12358:6;;12365:1;12358:9;;;;;-1:-1:-1;;;12358:9:20;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;12351:30:20;;:52;:30;:52::i;:::-;11984:3;;;;:::i;:::-;;;;11945:483;;;;11845:589;;;:::o;14212:84::-;2758:7;2784:6;-1:-1:-1;;;;;2784:6:20;170:10:17;2924:23:20;2916:68;;;;-1:-1:-1;;;2916:68:20;;15522:2:21;2916:68:20;;;15504:21:21;;;15541:18;;;15534:30;-1:-1:-1;;;;;;;;;;;15580:18:21;;;15573:62;15652:18;;2916:68:20;15494:182:21;2916:68:20;14282:7:::1;::::0;;14271:18;;::::1;-1:-1:-1::0;;;14282:7:20;;;::::1;;;14281:8;14271:18:::0;;::::1;;::::0;;14212:84::o;10841:125::-;2758:7;2784:6;-1:-1:-1;;;;;2784:6:20;170:10:17;2924:23:20;2916:68;;;;-1:-1:-1;;;2916:68:20;;15522:2:21;2916:68:20;;;15504:21:21;;;15541:18;;;15534:30;-1:-1:-1;;;;;;;;;;;15580:18:21;;;15573:62;15652:18;;2916:68:20;15494:182:21;2916:68:20;-1:-1:-1;;;;;10927:22:20;;;::::1;;::::0;;;:10:::1;:22;::::0;;;;:32;;-1:-1:-1;;10927:32:20::1;::::0;::::1;;::::0;;;::::1;::::0;;10841:125::o;5840:84:3:-;2758:7:20;2784:6;-1:-1:-1;;;;;2784:6:20;170:10:17;2924:23:20;2916:68;;;;-1:-1:-1;;;2916:68:20;;15522:2:21;2916:68:20;;;15504:21:21;;;15541:18;;;15534:30;-1:-1:-1;;;;;;;;;;;15580:18:21;;;15573:62;15652:18;;2916:68:20;15494:182:21;2916:68:20;5905:4:3::1;:12:::0;;-1:-1:-1;;5905:12:3::1;-1:-1:-1::0;;;;;5905:12:3;;;::::1;::::0;;;::::1;::::0;;5840:84::o;10084:198:20:-;2758:7;2784:6;-1:-1:-1;;;;;2784:6:20;170:10:17;2924:23:20;2916:68;;;;-1:-1:-1;;;2916:68:20;;15522:2:21;2916:68:20;;;15504:21:21;;;15541:18;;;15534:30;-1:-1:-1;;;;;;;;;;;15580:18:21;;;15573:62;15652:18;;2916:68:20;15494:182:21;2916:68:20;10207:3:::1;10190:13;:20;;10160:81;;;::::0;-1:-1:-1;;;10160:81:20;;14076:2:21;10160:81:20::1;::::0;::::1;14058:21:21::0;14115:2;14095:18;;;14088:30;14154:28;14134:18;;;14127:56;14200:18;;10160:81:20::1;14048:176:21::0;10160:81:20::1;10251:8;:24:::0;10084:198::o;11130:547::-;2758:7;2784:6;-1:-1:-1;;;;;2784:6:20;170:10:17;2924:23:20;2916:68;;;;-1:-1:-1;;;2916:68:20;;15522:2:21;2916:68:20;;;15504:21:21;;;15541:18;;;15534:30;-1:-1:-1;;;;;;;;;;;15580:18:21;;;15573:62;15652:18;;2916:68:20;15494:182:21;2916:68:20;11215:9:::1;11210:461;11230:17:::0;;::::1;11210:461;;;11268:11;4667:42;11298:6:::0;;11305:1;11298:9;;::::1;;;-1:-1:-1::0;;;11298:9:20::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;11298:23:20::1;;11294:367;;;11371:21;:32;11393:6;;11400:1;11393:9;;;;;-1:-1:-1::0;;;11393:9:20::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;11371:32:20::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;11371:32:20;;11347:56:::1;::::0;:21:::1;:56;:::i;:::-;11341:62;;11422:40;11448:7;2758::::0;2784:6;-1:-1:-1;;;;;2784:6:20;;2712:85;11448:7:::1;11458:3;11422:17;:40::i;:::-;11294:367;;;11552:21;:32;11574:6;;11581:1;11574:9;;;;;-1:-1:-1::0;;;11574:9:20::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;11552:32:20::1;-1:-1:-1::0;;;;;11552:32:20::1;;;;;;;;;;;;;11514:6;;11521:1;11514:9;;;;;-1:-1:-1::0;;;11514:9:20::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11507:42;::::0;-1:-1:-1;;;11507:42:20;;11543:4:::1;11507:42;::::0;::::1;6845:74:21::0;-1:-1:-1;;;;;11507:27:20;;;::::1;::::0;::::1;::::0;6818:18:21;;11507:42:20::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:77;;;;:::i;:::-;11501:83;;11602:44;11633:7;2758::::0;2784:6;-1:-1:-1;;;;;2784:6:20;;2712:85;11633:7:::1;11642:3;11609:6;;11616:1;11609:9;;;;;-1:-1:-1::0;;;11609:9:20::1;;;;;;;;11602:44;-1:-1:-1::0;11249:3:20;::::1;::::0;::::1;:::i;:::-;;;;11210:461;;;;11130:547:::0;;:::o;3344:145::-;2758:7;2784:6;-1:-1:-1;;;;;2784:6:20;170:10:17;2924:23:20;2916:68;;;;-1:-1:-1;;;2916:68:20;;15522:2:21;2916:68:20;;;15504:21:21;;;15541:18;;;15534:30;-1:-1:-1;;;;;;;;;;;15580:18:21;;;15573:62;15652:18;;2916:68:20;15494:182:21;2916:68:20;3450:1:::1;3434:6:::0;;3413:40:::1;::::0;-1:-1:-1;;;;;3434:6:20;;::::1;::::0;3413:40:::1;::::0;3450:1;;3413:40:::1;3480:1;3463:19:::0;;-1:-1:-1;;3463:19:20::1;::::0;;3344:145::o;12625:331::-;2758:7;2784:6;-1:-1:-1;;;;;2784:6:20;170:10:17;2924:23:20;2916:68;;;;-1:-1:-1;;;2916:68:20;;15522:2:21;2916:68:20;;;15504:21:21;;;15541:18;;;15534:30;-1:-1:-1;;;;;;;;;;;15580:18:21;;;15573:62;15652:18;;2916:68:20;15494:182:21;2916:68:20;12766:35;;::::1;12758:68;;;::::0;-1:-1:-1;;;12758:68:20;;14431:2:21;12758:68:20::1;::::0;::::1;14413:21:21::0;14470:2;14450:18;;;14443:30;14509:22;14489:18;;;14482:50;14549:18;;12758:68:20::1;14403:170:21::0;12758:68:20::1;12842:9;12837:113;12857:18:::0;;::::1;12837:113;;;12926:10;;12937:1;12926:13;;;;;-1:-1:-1::0;;;12926:13:20::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12896:15;:27;12912:7;;12920:1;12912:10;;;;;-1:-1:-1::0;;;12912:10:20::1;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;12896:27:20::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;12896:27:20;:43;;-1:-1:-1;;12896:43:20::1;::::0;::::1;;::::0;;;::::1;::::0;;12877:3;::::1;::::0;::::1;:::i;:::-;;;;12837:113;;;;12625:331:::0;;;;:::o;3604:1042:3:-;3879:14;4755:7:20;;-1:-1:-1;;;4755:7:20;;;;4754:8;4746:27;;;;-1:-1:-1;;;4746:27:20;;10048:2:21;4746:27:20;;;10030:21:21;10087:1;10067:18;;;10060:29;-1:-1:-1;;;10105:18:21;;;10098:36;10151:18;;4746:27:20;10020:155:21;4746:27:20;3937:16:3::1;3956:48;3968:9;3979:8;3989;3999:4;3956:11;:48::i;:::-;3937:67;;4059:20;4082:146;4106:9;4129;4164:8;4186:10;4210:8;;4082:146;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;4082:10:3::1;::::0;-1:-1:-1;;;4082:146:3:i:1;:::-;4343:4;::::0;4059:169;;-1:-1:-1;4318:44:3::1;::::0;4332:9;;-1:-1:-1;;;;;4343:4:3::1;4059:169:::0;4318:13:::1;:44::i;:::-;4425:4;::::0;4413:162:::1;::::0;;;;::::1;::::0;::::1;17314:25:21::0;;;17355:18;;;17348:34;;;17398:18;;;17391:34;;;4520:10:3::1;17502:18:21::0;;;17495:43;-1:-1:-1;;;;;17575:15:21;;;17554:19;;;17547:44;4425:4:3;;::::1;::::0;4413:25:::1;::::0;17286:19:21;;4413:162:3::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;4591:48:3::1;::::0;;4599:10:::1;7957:34:21::0;;-1:-1:-1;;;;;8027:15:21;;;8022:2;8007:18;;8000:43;8059:18;;;8052:34;;;8122:15;;;8117:2;8102:18;;8095:43;4398:177:3;;-1:-1:-1;4591:48:3::1;::::0;7883:3:21;7868:19;4591:48:3::1;;;;;;;4783:1:20;;3604:1042:3::0;;;;;;;;;;;:::o;5700:96::-;2758:7:20;2784:6;-1:-1:-1;;;;;2784:6:20;170:10:17;2924:23:20;2916:68;;;;-1:-1:-1;;;2916:68:20;;15522:2:21;2916:68:20;;;15504:21:21;;;15541:18;;;15534:30;-1:-1:-1;;;;;;;;;;;15580:18:21;;;15573:62;15652:18;;2916:68:20;15494:182:21;2916:68:20;5771:7:3::1;:18:::0;;-1:-1:-1;;5771:18:3::1;-1:-1:-1::0;;;;;5771:18:3;;;::::1;::::0;;;::::1;::::0;;5700:96::o;2235:741::-;2487:14;4755:7:20;;-1:-1:-1;;;4755:7:20;;;;4754:8;4746:27;;;;-1:-1:-1;;;4746:27:20;;10048:2:21;4746:27:20;;;10030:21:21;10087:1;10067:18;;;10060:29;-1:-1:-1;;;10105:18:21;;;10098:36;10151:18;;4746:27:20;10020:155:21;4746:27:20;2545:16:3::1;2564:48;2576:9;2587:8;2597;2607:4;2564:11;:48::i;:::-;2545:67;;2656:20;2679:58;2690:9;2701:3;2706:8;2716:10;2728:8;;2679:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;2679:10:3::1;::::0;-1:-1:-1;;;2679:58:3:i:1;:::-;2656:81;;2795:29;2802:12;2816:7;2795:6;:29::i;:::-;2786:38;;2878:10;2869:6;:19;2861:45;;;::::0;-1:-1:-1;;;2861:45:3;;10735:2:21;2861:45:3::1;::::0;::::1;10717:21:21::0;10774:2;10754:18;;;10747:30;10813:15;10793:18;;;10786:43;10846:18;;2861:45:3::1;10707:163:21::0;2861:45:3::1;2922:47;::::0;;2931:10:::1;7957:34:21::0;;-1:-1:-1;;;;;8027:15:21;;;8022:2;8007:18;;8000:43;8059:18;;;8052:34;;;8122:15;;8117:2;8102:18;;8095:43;2922:47:3;;::::1;::::0;;;;7883:3:21;2922:47:3;;::::1;4783:1:20;;2235:741:3::0;;;;;;;;;;:::o;3638:240:20:-;2758:7;2784:6;-1:-1:-1;;;;;2784:6:20;170:10:17;2924:23:20;2916:68;;;;-1:-1:-1;;;2916:68:20;;15522:2:21;2916:68:20;;;15504:21:21;;;15541:18;;;15534:30;-1:-1:-1;;;;;;;;;;;15580:18:21;;;15573:62;15652:18;;2916:68:20;15494:182:21;2916:68:20;-1:-1:-1;;;;;3726:22:20;::::1;3718:73;;;::::0;-1:-1:-1;;;3718:73:20;;11077:2:21;3718:73:20::1;::::0;::::1;11059:21:21::0;11116:2;11096:18;;;11089:30;11155:34;11135:18;;;11128:62;11226:8;11206:18;;;11199:36;11252:19;;3718:73:20::1;11049:228:21::0;3718:73:20::1;3827:6;::::0;;3806:38:::1;::::0;-1:-1:-1;;;;;3806:38:20;;::::1;::::0;3827:6;::::1;::::0;3806:38:::1;::::0;::::1;3854:6;:17:::0;;-1:-1:-1;;3854:17:20::1;-1:-1:-1::0;;;;;3854:17:20;;;::::1;::::0;;;::::1;::::0;;3638:240::o;9836:128::-;2758:7;2784:6;-1:-1:-1;;;;;2784:6:20;170:10:17;2924:23:20;2916:68;;;;-1:-1:-1;;;2916:68:20;;15522:2:21;2916:68:20;;;15504:21:21;;;15541:18;;;15534:30;-1:-1:-1;;;;;;;;;;;15580:18:21;;;15573:62;15652:18;;2916:68:20;15494:182:21;2916:68:20;-1:-1:-1;;;;;9924:24:20;;;::::1;;::::0;;;:12:::1;:24;::::0;;;;:33;;-1:-1:-1;;9924:33:20::1;::::0;::::1;;::::0;;;::::1;::::0;;9836:128::o;2071:459:16:-;2198:6;2173:21;:31;;2152:107;;;;-1:-1:-1;;;2152:107:16;;13311:2:21;2152:107:16;;;13293:21:21;13350:2;13330:18;;;13323:30;13389:31;13369:18;;;13362:59;13438:18;;2152:107:16;13283:179:21;2152:107:16;2348:12;2366:9;-1:-1:-1;;;;;2366:14:16;2389:6;2366:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2347:54;;;2432:7;2411:112;;;;-1:-1:-1;;;2411:112:16;;12535:2:21;2411:112:16;;;12517:21:21;12574:2;12554:18;;;12547:30;12613:34;12593:18;;;12586:62;12684:28;12664:18;;;12657:56;12730:19;;2411:112:16;12507:248:21;178:239:18;342:58;;-1:-1:-1;;;;;8341:55:21;;342:58:18;;;8323:74:21;8413:18;;;8406:34;;;290:120:18;;323:5;;365:23;;8296:18:21;;342:58:18;;;;-1:-1:-1;;342:58:18;;;;;;;;;;;;;;;;;;;;;;;;;;;290:19;:120::i;5230:870:20:-;5386:7;;-1:-1:-1;;;;;5448:19:20;;5444:324;;5503:1;5491:9;:13;5483:37;;;;-1:-1:-1;;;5483:37:20;;15182:2:21;5483:37:20;;;15164:21:21;15221:2;15201:18;;;15194:30;15260:13;15240:18;;;15233:41;15291:18;;5483:37:20;15154:161:21;5483:37:20;5558:145;4667:42;5621:9;5648;5675:14;5558:17;:145::i;:::-;5535:168;-1:-1:-1;5725:32:20;5535:168;5725:9;:32;:::i;:::-;5718:39;;;;;5444:324;5795:1;5786:6;:10;5778:43;;;;-1:-1:-1;;;5778:43:20;;12962:2:21;5778:43:20;;;12944:21:21;13001:2;12981:18;;;12974:30;13040:22;13020:18;;;13013:50;13080:18;;5778:43:20;12934:170:21;5778:43:20;5839:9;:14;5831:46;;;;-1:-1:-1;;;5831:46:20;;11484:2:21;5831:46:20;;;11466:21:21;11523:2;11503:18;;;11496:30;11562:21;11542:18;;;11535:49;11601:18;;5831:46:20;11456:169:21;5831:46:20;5888:65;-1:-1:-1;;;;;5888:30:20;;5919:10;5939:4;5946:6;5888:30;:65::i;:::-;5987:59;6005:5;6012:6;6020:9;6031:14;5987:17;:59::i;:::-;5964:82;-1:-1:-1;6064:29:20;5964:82;6064:6;:29;:::i;:::-;6057:36;;;5230:870;;;;;;;:::o;6941:1193::-;7128:20;7177:7;-1:-1:-1;;;;;7164:20:20;:9;-1:-1:-1;;;;;7164:20:20;;7160:64;;;-1:-1:-1;7207:6:20;7200:13;;7160:64;-1:-1:-1;;;;;7238:23:20;;;:54;;;;-1:-1:-1;;;;;;7265:27:20;;4029:42;7265:27;7238:54;7234:162;;;4029:42;-1:-1:-1;;;;;7308:31:20;;7348:6;7308:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7379:6;7372:13;;;;7234:162;-1:-1:-1;;;;;7410:29:20;;4029:42;7410:29;:54;;;;-1:-1:-1;;;;;;7443:21:20;;;7410:54;7406:152;;;7480:40;;;;;;;;17019:25:21;;;4029:42:20;;7480:32;;16992:18:21;;7480:40:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7541:6;7534:13;;;;7406:152;7568:19;-1:-1:-1;;;;;7601:23:20;;7597:149;;-1:-1:-1;7654:6:20;7597:149;;;7691:44;7705:9;7716:10;7728:6;7691:13;:44::i;:::-;7756:22;7781:20;7793:7;7781:11;:20::i;:::-;-1:-1:-1;;;;;7820:27:20;;;;;;:15;:27;;;;;;7756:45;;-1:-1:-1;7820:27:20;;7812:61;;;;-1:-1:-1;;;7812:61:20;;9698:2:21;7812:61:20;;;9680:21:21;9737:2;9717:18;;;9710:30;9776:23;9756:18;;;9749:51;9817:18;;7812:61:20;9670:171:21;7812:61:20;7884:12;7902:10;-1:-1:-1;;;;;7902:15:20;7926:11;7940:8;7902:47;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7883:66;;;7967:7;7959:41;;;;-1:-1:-1;;;7959:41:20;;11832:2:21;7959:41:20;;;11814:21:21;11871:2;11851:18;;;11844:30;11910:23;11890:18;;;11883:51;11951:18;;7959:41:20;11804:171:21;7959:41:20;8049:14;8026:20;8038:7;8026:11;:20::i;:::-;:37;;;;:::i;:::-;8011:52;;8097:1;8082:12;:16;8074:53;;;;-1:-1:-1;;;8074:53:20;;12182:2:21;8074:53:20;;;12164:21:21;12221:2;12201:18;;;12194:30;12260:26;12240:18;;;12233:54;12304:18;;8074:53:20;12154:174:21;8074:53:20;6941:1193;;;;;;;;;;;:::o;9317:282::-;-1:-1:-1;;;;;9441:19:20;;;;:44;;-1:-1:-1;;;;;;9464:21:20;;;9441:44;9437:57;;;9317:282;;;:::o;9437:57::-;9503:37;-1:-1:-1;;;;;9503:25:20;;9529:7;9538:1;9503:25;:37::i;:::-;9550:42;-1:-1:-1;;;;;9550:25:20;;9576:7;9585:6;9550:25;:42::i;4899:683:3:-;5080:7;;4966;;;;5061:35;;5075:3;;-1:-1:-1;;;;;5080:7:3;5089:6;5061:13;:35::i;:::-;5122:4;-1:-1:-1;;;;;5111:15:3;:7;-1:-1:-1;;;;;5111:15:3;;5107:259;;;5200:7;;5191:59;;-1:-1:-1;;;5191:59:3;;5223:4;5191:59;;;8670:74:21;8760:18;;;8753:34;;;5200:7:3;8803:18:21;;;8796:50;5200:7:3;8862:18:21;;;8855:50;-1:-1:-1;;;;;5200:7:3;;;;5191:23;;8642:19:21;;5191:59:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5175:75;-1:-1:-1;5265:55:3;-1:-1:-1;;;;;5265:28:3;;5294:10;5175:75;5265:28;:55::i;:::-;5342:13;-1:-1:-1;5335:20:3;;5107:259;5429:7;;5420:58;;-1:-1:-1;;;5420:58:3;;5452:4;5420:58;;;8670:74:21;8760:18;;;8753:34;;;5429:7:3;8803:18:21;;;8796:50;;;8862:18;;;8855:50;-1:-1:-1;;;;;5429:7:3;;;;5420:23;;8642:19:21;;5420:58:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5404:74;-1:-1:-1;5489:55:3;-1:-1:-1;;;;;5489:28:3;;5518:10;5404:74;5489:28;:55::i;:::-;5562:13;-1:-1:-1;4899:683:3;;;;;:::o;3105:867:18:-;3524:23;3562:115;3607:4;3562:115;;;;;;;;;;;;;;;;;3570:5;-1:-1:-1;;;;;3562:27:18;;;:115;;;;;:::i;:::-;3691:17;;3524:153;;-1:-1:-1;3691:21:18;3687:279;;3860:10;3849:30;;;;;;;;;;;;:::i;:::-;3824:131;;;;-1:-1:-1;;;3824:131:18;;16241:2:21;3824:131:18;;;16223:21:21;16280:2;16260:18;;;16253:30;16319:34;16299:18;;;16292:62;16390:12;16370:18;;;16363:40;16420:19;;3824:131:18;16213:232:21;13379:766:20;13605:10;13533:28;13592:24;;;:12;:24;;;;;;13630:8;;13592:24;;;;;13630:12;;;;:30;;;13646:14;13630:30;:46;;;;;13665:11;13664:12;13630:46;13626:513;;;13737:5;13725:8;;13716:6;:17;;;;:::i;:::-;13715:27;;;;:::i;:::-;-1:-1:-1;;;;;13761:21:20;;;;;;:10;:21;;;;;;13692:50;;-1:-1:-1;13761:21:20;;13757:372;;;-1:-1:-1;;;;;13806:19:20;;13802:84;;4667:42;13849:18;;13802:84;13904:24;13973:3;13955:14;;13932:20;:37;;;;:::i;:::-;13931:45;;;;:::i;:::-;-1:-1:-1;;;;;13994:27:20;;;;;;;:16;:27;;;;;;;;:34;;;;;;;;;;;:54;;13904:72;;-1:-1:-1;13904:72:20;;13994:34;;:27;:54;;13904:72;;13994:54;:::i;:::-;;;;-1:-1:-1;;;;;;;14066:28:20;;;;;;:21;:28;;;;;:48;;14098:16;;14066:28;:48;;14098:16;;14066:48;:::i;:::-;;;;-1:-1:-1;;;13757:372:20;13379:766;;;;;;;:::o;423:275:18:-;613:68;;-1:-1:-1;;;;;7543:15:21;;;613:68:18;;;7525:34:21;7595:15;;7575:18;;;7568:43;7627:18;;;7620:34;;;561:130:18;;594:5;;636:27;;7437:18:21;;613:68:18;7419:241:21;8334:252:20;8393:15;-1:-1:-1;;;;;8424:19:20;;8420:160;;-1:-1:-1;8469:21:20;8334:252;;;:::o;8420:160::-;8531:38;;-1:-1:-1;;;8531:38:20;;8563:4;8531:38;;;6845:74:21;-1:-1:-1;;;;;8531:23:20;;;;;6818:18:21;;8531:38:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8521:48;;8420:160;8334:252;;;:::o;958:690:18:-;1366:10;;;1365:62;;-1:-1:-1;1382:39:18;;;;;1406:4;1382:39;;;7165:34:21;-1:-1:-1;;;;;7235:15:21;;;7215:18;;;7208:43;1382:15:18;;;;;7077:18:21;;1382:39:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;1365:62;1344:163;;;;-1:-1:-1;;;1344:163:18;;16652:2:21;1344:163:18;;;16634:21:21;16691:2;16671:18;;;16664:30;16730:34;16710:18;;;16703:62;16801:24;16781:18;;;16774:52;16843:19;;1344:163:18;16624:244:21;1344:163:18;1569:62;;-1:-1:-1;;;;;8341:55:21;;1569:62:18;;;8323:74:21;8413:18;;;8406:34;;;1517:124:18;;1550:5;;1592:22;;8296:18:21;;1569:62:18;8278:168:21;3686:223:16;3819:12;3850:52;3872:6;3880:4;3886:1;3889:12;3850:21;:52::i;:::-;3843:59;;3686:223;;;;;;:::o;4863:607::-;5028:12;5098:5;5073:21;:30;;5052:115;;;;-1:-1:-1;;;5052:115:16;;13669:2:21;5052:115:16;;;13651:21:21;13708:2;13688:18;;;13681:30;13747:34;13727:18;;;13720:62;13818:8;13798:18;;;13791:36;13844:19;;5052:115:16;13641:228:21;5052:115:16;1093:20;;5177:60;;;;-1:-1:-1;;;5177:60:16;;15883:2:21;5177:60:16;;;15865:21:21;15922:2;15902:18;;;15895:30;15961:31;15941:18;;;15934:59;16010:18;;5177:60:16;15855:179:21;5177:60:16;5308:12;5322:23;5361:6;-1:-1:-1;;;;;5361:11:16;5381:5;5389:4;5361:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5307:87;;;;5411:52;5429:7;5438:10;5450:12;5411:17;:52::i;:::-;5404:59;4863:607;-1:-1:-1;;;;;;;4863:607:16:o;7686:756::-;7832:12;7860:7;7856:580;;;-1:-1:-1;7890:10:16;7883:17;;7856:580;8001:17;;:21;7997:429;;8259:10;8253:17;8319:15;8306:10;8302:2;8298:19;8291:44;8208:145;8398:12;8391:20;;-1:-1:-1;;;8391:20:16;;;;;;;;:::i;14:196:21:-;82:20;;-1:-1:-1;;;;;131:54:21;;121:65;;111:2;;200:1;197;190:12;215:395;278:8;288:6;342:3;335:4;327:6;323:17;319:27;309:2;;367:8;357;350:26;309:2;-1:-1:-1;397:20:21;;440:18;429:30;;426:2;;;479:8;469;462:26;426:2;523:4;515:6;511:17;499:29;;583:3;576:4;566:6;563:1;559:14;551:6;547:27;543:38;540:47;537:2;;;600:1;597;590:12;537:2;299:311;;;;;:::o;615:375::-;666:8;676:6;730:3;723:4;715:6;711:17;707:27;697:2;;755:8;745;738:26;697:2;-1:-1:-1;785:20:21;;828:18;817:30;;814:2;;;867:8;857;850:26;814:2;911:4;903:6;899:17;887:29;;963:3;956:4;947:6;939;935:19;931:30;928:39;925:2;;;980:1;977;970:12;995:196;1054:6;1107:2;1095:9;1086:7;1082:23;1078:32;1075:2;;;1128:6;1120;1113:22;1075:2;1156:29;1175:9;1156:29;:::i;1196:270::-;1264:6;1272;1325:2;1313:9;1304:7;1300:23;1296:32;1293:2;;;1346:6;1338;1331:22;1293:2;1374:29;1393:9;1374:29;:::i;:::-;1364:39;;1422:38;1456:2;1445:9;1441:18;1422:38;:::i;:::-;1412:48;;1283:183;;;;;:::o;1471:325::-;1536:6;1544;1597:2;1585:9;1576:7;1572:23;1568:32;1565:2;;;1618:6;1610;1603:22;1565:2;1646:29;1665:9;1646:29;:::i;:::-;1636:39;;1725:2;1714:9;1710:18;1697:32;1738:28;1760:5;1738:28;:::i;:::-;1785:5;1775:15;;;1555:241;;;;;:::o;1801:934::-;1934:6;1942;1950;1958;1966;1974;1982;1990;1998;2051:3;2039:9;2030:7;2026:23;2022:33;2019:2;;;2073:6;2065;2058:22;2019:2;2101:29;2120:9;2101:29;:::i;:::-;2091:39;;2177:2;2166:9;2162:18;2149:32;2139:42;;2200:38;2234:2;2223:9;2219:18;2200:38;:::i;:::-;2190:48;;2257:38;2291:2;2280:9;2276:18;2257:38;:::i;:::-;2247:48;;2346:3;2335:9;2331:19;2318:33;2374:18;2366:6;2363:30;2360:2;;;2411:6;2403;2396:22;2360:2;2455:58;2505:7;2496:6;2485:9;2481:22;2455:58;:::i;:::-;2532:8;;-1:-1:-1;2429:84:21;-1:-1:-1;2586:39:21;;-1:-1:-1;2620:3:21;2605:19;;2586:39;:::i;:::-;2576:49;;2672:3;2661:9;2657:19;2644:33;2634:43;;2724:3;2713:9;2709:19;2696:33;2686:43;;2009:726;;;;;;;;;;;:::o;2740:865::-;2864:6;2872;2880;2888;2896;2904;2912;2920;2973:3;2961:9;2952:7;2948:23;2944:33;2941:2;;;2995:6;2987;2980:22;2941:2;3023:29;3042:9;3023:29;:::i;:::-;3013:39;;3099:2;3088:9;3084:18;3071:32;3061:42;;3122:38;3156:2;3145:9;3141:18;3122:38;:::i;:::-;3112:48;;3207:2;3196:9;3192:18;3179:32;3169:42;;3230:39;3264:3;3253:9;3249:19;3230:39;:::i;:::-;3220:49;;3320:3;3309:9;3305:19;3292:33;3348:18;3340:6;3337:30;3334:2;;;3385:6;3377;3370:22;3334:2;3429:58;3479:7;3470:6;3459:9;3455:22;3429:58;:::i;:::-;3506:8;;-1:-1:-1;3403:84:21;-1:-1:-1;3560:39:21;;-1:-1:-1;3594:3:21;3579:19;;3560:39;:::i;:::-;3550:49;;2931:674;;;;;;;;;;;:::o;3610:457::-;3696:6;3704;3757:2;3745:9;3736:7;3732:23;3728:32;3725:2;;;3778:6;3770;3763:22;3725:2;3823:9;3810:23;3856:18;3848:6;3845:30;3842:2;;;3893:6;3885;3878:22;3842:2;3937:70;3999:7;3990:6;3979:9;3975:22;3937:70;:::i;:::-;4026:8;;3911:96;;-1:-1:-1;3715:352:21;-1:-1:-1;;;;3715:352:21:o;4072:800::-;4191:6;4199;4207;4215;4268:2;4256:9;4247:7;4243:23;4239:32;4236:2;;;4289:6;4281;4274:22;4236:2;4334:9;4321:23;4363:18;4404:2;4396:6;4393:14;4390:2;;;4425:6;4417;4410:22;4390:2;4469:70;4531:7;4522:6;4511:9;4507:22;4469:70;:::i;:::-;4558:8;;-1:-1:-1;4443:96:21;-1:-1:-1;4646:2:21;4631:18;;4618:32;;-1:-1:-1;4662:16:21;;;4659:2;;;4696:6;4688;4681:22;4659:2;;4740:72;4804:7;4793:8;4782:9;4778:24;4740:72;:::i;:::-;4226:646;;;;-1:-1:-1;4831:8:21;-1:-1:-1;;;;4226:646:21:o;4877:251::-;4933:6;4986:2;4974:9;4965:7;4961:23;4957:32;4954:2;;;5007:6;4999;4992:22;4954:2;5051:9;5038:23;5070:28;5092:5;5070:28;:::i;5133:255::-;5200:6;5253:2;5241:9;5232:7;5228:23;5224:32;5221:2;;;5274:6;5266;5259:22;5221:2;5311:9;5305:16;5330:28;5352:5;5330:28;:::i;5393:190::-;5452:6;5505:2;5493:9;5484:7;5480:23;5476:32;5473:2;;;5526:6;5518;5511:22;5473:2;-1:-1:-1;5554:23:21;;5463:120;-1:-1:-1;5463:120:21:o;5588:194::-;5658:6;5711:2;5699:9;5690:7;5686:23;5682:32;5679:2;;;5732:6;5724;5717:22;5679:2;-1:-1:-1;5760:16:21;;5669:113;-1:-1:-1;5669:113:21:o;5787:418::-;5874:6;5882;5890;5943:2;5931:9;5922:7;5918:23;5914:32;5911:2;;;5964:6;5956;5949:22;5911:2;5998:9;5992:16;5982:26;;6048:2;6037:9;6033:18;6027:25;6017:35;;6095:2;6084:9;6080:18;6074:25;6139:6;6132:5;6128:18;6121:5;6118:29;6108:2;;6166:6;6158;6151:22;6108:2;6194:5;6184:15;;;5901:304;;;;;:::o;6210:274::-;6339:3;6377:6;6371:13;6393:53;6439:6;6434:3;6427:4;6419:6;6415:17;6393:53;:::i;:::-;6462:16;;;;;6347:137;-1:-1:-1;;6347:137:21:o;9108:383::-;9257:2;9246:9;9239:21;9220:4;9289:6;9283:13;9332:6;9327:2;9316:9;9312:18;9305:34;9348:66;9407:6;9402:2;9391:9;9387:18;9382:2;9374:6;9370:15;9348:66;:::i;:::-;9475:2;9454:15;-1:-1:-1;;9450:29:21;9435:45;;;;9482:2;9431:54;;9229:262;-1:-1:-1;;9229:262:21:o;17602:128::-;17642:3;17673:1;17669:6;17666:1;17663:13;17660:2;;;17679:18;;:::i;:::-;-1:-1:-1;17715:9:21;;17650:80::o;17735:274::-;17775:1;17801;17791:2;;-1:-1:-1;;;17833:1:21;17826:88;17937:4;17934:1;17927:15;17965:4;17962:1;17955:15;17791:2;-1:-1:-1;17994:9:21;;17781:228::o;18014:168::-;18054:7;18120:1;18116;18112:6;18108:14;18105:1;18102:21;18097:1;18090:9;18083:17;18079:45;18076:2;;;18127:18;;:::i;:::-;-1:-1:-1;18167:9:21;;18066:116::o;18187:125::-;18227:4;18255:1;18252;18249:8;18246:2;;;18260:18;;:::i;:::-;-1:-1:-1;18297:9:21;;18236:76::o;18317:258::-;18389:1;18399:113;18413:6;18410:1;18407:13;18399:113;;;18489:11;;;18483:18;18470:11;;;18463:39;18435:2;18428:10;18399:113;;;18530:6;18527:1;18524:13;18521:2;;;-1:-1:-1;;18565:1:21;18547:16;;18540:27;18370:205::o;18580:135::-;18619:3;-1:-1:-1;;18640:17:21;;18637:2;;;18660:18;;:::i;:::-;-1:-1:-1;18707:1:21;18696:13;;18627:88::o;18720:184::-;-1:-1:-1;;;18769:1:21;18762:88;18869:4;18866:1;18859:15;18893:4;18890:1;18883:15;18909:118;18995:5;18988:13;18981:21;18974:5;18971:32;18961:2;;19017:1;19014;19007:12;18961:2;18951:76;:::o
Swarm Source
ipfs://91222a19ea774491eec7467aa9a8d141266aef109ac42b1c8f4ebb95e7f4bdb2
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.