Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
SimpleSettlement
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 10000 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; // external libraries import {OwnableUpgradeable} from "openzeppelin-upgradeable/access/OwnableUpgradeable.sol"; import {ReentrancyGuardUpgradeable} from "openzeppelin-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import {SafeERC20} from "openzeppelin/token/ERC20/utils/SafeERC20.sol"; import {UUPSUpgradeable} from "openzeppelin/proxy/utils/UUPSUpgradeable.sol"; // interfaces import {IERC20, IHnToken} from "../interfaces/IHnToken.sol"; import {IAssetRegistry} from "../interfaces/IAssetRegistry.sol"; import {IAuctionVault} from "../interfaces/IAuctionVault.sol"; import {IMarginEngine} from "../interfaces/IMarginEngine.sol"; import {IAuthority, Role} from "entitlements/src/interfaces/IAuthority.sol"; // libraries import {ActionUtil} from "../libraries/ActionUtil.sol"; import "../config/types.sol"; import "../config/errors.sol"; import "../config/constants.sol"; contract SimpleSettlement is OwnableUpgradeable, ReentrancyGuardUpgradeable, UUPSUpgradeable { using ActionUtil for ActionArgs[]; using ActionUtil for BatchExecute[]; using SafeERC20 for IERC20; /*/////////////////////////////////////////////////////////////// Constants and Immutables //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; address public immutable ME_CASH; address public immutable ME_PHYSICAL; IAuthority public immutable authority; /*/////////////////////////////////////////////////////////////// Storage V1 //////////////////////////////////////////////////////////////*/ mapping(uint256 => bool) public noncesUsed; mapping(address => address) public wrapToken; mapping(address => address) public unWrapToken; /*/////////////////////////////////////////////////////////////// Events //////////////////////////////////////////////////////////////*/ event TokenMapSet(address indexed token0, address token1); event SettledBid(uint256 nonce, address indexed vault, address indexed counterparty); event SettledBids(uint256[] nonces, address[] vaults, address indexed counterparty); /*/////////////////////////////////////////////////////////////// Constructor //////////////////////////////////////////////////////////////*/ constructor(address _meCash, address _mePhysical, address _authority) initializer { if (_meCash == address(0) || _mePhysical == address(0) || _authority == address(0)) revert BadAddress(); INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = _computeDomainSeparator(); ME_CASH = _meCash; ME_PHYSICAL = _mePhysical; authority = IAuthority(_authority); } function initialize(address _owner) external initializer { if (_owner == address(0)) revert BadAddress(); _transferOwnership(_owner); __ReentrancyGuard_init_unchained(); } /*/////////////////////////////////////////////////////////////// External Functions //////////////////////////////////////////////////////////////*/ /** * @notice Withdraws cross chain token from the margin account and burns it to initiate transfer on a native chain * @param _marginEngine is the address of the margin engine * @param _collateralId is the id of the collateral * @param _amount is the amount of the collateral to withdraw * @param _recipient is the address of the recipient on a native chain */ function burn(address _marginEngine, uint8 _collateralId, uint256 _amount, string calldata _recipient) external { _burn(_marginEngine, _collateralId, _amount, _recipient, msg.sender); } function burnOnBehalfOf( address _marginEngine, uint8 _collateralId, uint256 _amount, string calldata _recipient, address _onBehalfOf ) external { _assertFundAdmin(); _burn(_marginEngine, _collateralId, _amount, _recipient, _onBehalfOf); } function _burn(address _marginEngine, uint8 _collateralId, uint256 _amount, string calldata _recipient, address _onBehalfOf) internal { IMarginEngine marginEngine = IMarginEngine(_marginEngine); // remove collateral from the margin account ActionArgs[] memory actions = new ActionArgs[](1); actions[0] = ActionArgs({action: REMOVE_COLLATERAL_ACTION, data: abi.encode(uint80(_amount), address(this), _collateralId)}); marginEngine.execute(_onBehalfOf, actions); IAssetRegistry assetRegistry = _marginEngine == ME_CASH ? marginEngine.grappa() : marginEngine.pomace(); (address addr,) = assetRegistry.assets(_collateralId); // burn tokens in order to initiate transfer on a native chain for a recipient IHnToken(addr).burn(_amount, _recipient); } /** * @notice Wraps token in margin account * @param _marginEngine address of margin engine * @param _subAccount account in which the tokens will be swapped * @param _collateralId the id of the asset to be wrapped * @param _amount the amount of the asset to be wrapped */ function wrap(address _marginEngine, address _subAccount, uint8 _collateralId, uint256 _amount) external nonReentrant { IMarginEngine marginEngine = IMarginEngine(_marginEngine); bool isCashSettled = address(marginEngine) == ME_CASH; IAssetRegistry assetRegistry = isCashSettled ? marginEngine.grappa() : marginEngine.pomace(); // withdraw underlying from margin account ActionArgs[] memory actions = new ActionArgs[](1); actions[0] = ActionArgs({action: REMOVE_COLLATERAL_ACTION, data: abi.encode(uint80(_amount), address(this), _collateralId)}); marginEngine.execute(_subAccount, actions); (address underlying,) = assetRegistry.assets(_collateralId); // wrap underlying (address wrapper, uint256 amount) = _wrapToken(address(this), underlying, _amount, isCashSettled); if (wrapper == address(0)) revert BadAddress(); _collateralId = assetRegistry.assetIds(wrapper); // deposit wrapped token to margin account actions[0] = ActionArgs({action: ADD_COLLATERAL_ACTION, data: abi.encode(address(this), uint80(amount), _collateralId)}); marginEngine.execute(_subAccount, actions); } /** * @notice Wraps token in margin account * @param _marginEngine address of margin engine * @param _subAccount account in which the tokens will be swapped * @param _fromId the id of the asset to be wrapped * @param _toToken the address of the asset to be wrapped into * @param _amount the amount of the asset to be wrapped */ function wrapTo(IMarginEngine _marginEngine, address _subAccount, uint8 _fromId, address _toToken, uint256 _amount) external nonReentrant returns (uint256 amount) { _assertFundAdmin(); uint8 toId = (address(_marginEngine) == ME_CASH ? _marginEngine.grappa() : _marginEngine.pomace()).assetIds(_toToken); if (toId == 0) revert BadAddress(); // withdraw underlying from margin account ActionArgs[] memory actions = new ActionArgs[](1); actions[0] = ActionArgs({action: REMOVE_COLLATERAL_ACTION, data: abi.encode(uint80(_amount), address(this), _fromId)}); _marginEngine.execute(_subAccount, actions); // deposits underlying to wrapper amount = IHnToken(_toToken).deposit(_amount); if (amount == 0) revert BadAmount(); // deposit wrapped token to margin account actions[0] = ActionArgs({action: ADD_COLLATERAL_ACTION, data: abi.encode(address(this), uint80(amount), toId)}); _marginEngine.execute(_subAccount, actions); } /** * @notice Withdraws token from margin account * @param _marginEngine address of margin engine * @param _collateralId the id of the asset to be withdrawn * @param _amount the amount of the asset to be withdrawn * @param _v The recovery byte of the signature * @param _r is the r value of the signature * @param _s is the s value of the signature */ function withdraw(address _marginEngine, uint8 _collateralId, uint256 _amount, uint8 _v, bytes32 _r, bytes32 _s) external nonReentrant { _withdraw(_marginEngine, _collateralId, _amount, _v, _r, _s, msg.sender); } function withdrawOnBehalfOf( address _marginEngine, uint8 _collateralId, uint256 _amount, uint8 _v, bytes32 _r, bytes32 _s, address _onBehalfOf ) external nonReentrant { _assertFundAdmin(); _withdraw(_marginEngine, _collateralId, _amount, _v, _r, _s, _onBehalfOf); } function _withdraw( address _marginEngine, uint8 _collateralId, uint256 _amount, uint8 _v, bytes32 _r, bytes32 _s, address _onBehalfOf ) internal { IMarginEngine marginEngine = IMarginEngine(_marginEngine); IAssetRegistry assetRegistry = _marginEngine == ME_CASH ? marginEngine.grappa() : marginEngine.pomace(); (address wrapper,) = assetRegistry.assets(_collateralId); address underlying = unWrapToken[wrapper]; address receiver = address(this); if (underlying == address(0)) receiver = _onBehalfOf; ActionArgs[] memory actions = new ActionArgs[](1); actions[0] = ActionArgs({action: REMOVE_COLLATERAL_ACTION, data: abi.encode(uint80(_amount), receiver, _collateralId)}); marginEngine.execute(_onBehalfOf, actions); if (underlying != address(0)) IHnToken(wrapper).withdrawTo(_onBehalfOf, _amount, _v, _r, _s); } /** * @notice Exercises a token * @param _tokenId is the id of the token * @param _amount is the amount of the token to exercise */ function exercise(uint256 _tokenId, uint256 _amount, uint8 _collateralId, uint256 _collateralAmount) external nonReentrant { IMarginEngine marginEngine = IMarginEngine(ME_PHYSICAL); // pull collateral from the market maker (address collateralToken,) = marginEngine.pomace().assets(_collateralId); IERC20(collateralToken).safeTransferFrom(msg.sender, address(this), _collateralAmount); // deposit collateral into the margin account ActionArgs[] memory actions = new ActionArgs[](2); actions[0] = ActionArgs({action: ADD_COLLATERAL_ACTION, data: abi.encode(address(this), _collateralAmount, _collateralId)}); actions[1] = ActionArgs({action: EXERCISE_TOKEN_ACTION, data: abi.encode(_tokenId, uint64(_amount))}); marginEngine.execute(msg.sender, actions); } /** * @notice bulk revoke from margin account * @dev revokes access to margin accounts * @param _marginEngine address of margin engine * @param _subAccounts array of sub-accounts to itself from */ function revokeMarginAccountAccess(address _marginEngine, address[] calldata _subAccounts) external { _checkOwner(); IMarginEngine marginEngine = IMarginEngine(_marginEngine); for (uint256 i; i < _subAccounts.length;) { marginEngine.revokeSelfAccess(_subAccounts[i]); unchecked { ++i; } } } function setTokenMap(address _token0, address _token1) external { _checkOwner(); if (_token0 == address(0)) revert BadAddress(); wrapToken[_token0] = _token1; unWrapToken[_token1] = _token0; emit TokenMapSet(_token0, _token1); } function settleBatchFundAdminOnly( IMarginEngine _marginEngine, address[] calldata _from, IERC20[] calldata _token, uint256[] calldata _amount, IHnToken[] calldata _wrapper, BatchExecute[] memory _batch ) external { _assertFundAdmin(); for (uint256 i; i < _token.length;) { if (_from[i] != address(this)) _token[i].safeTransferFrom(_from[i], address(this), _amount[i]); if (address(_wrapper[i]) == address(0)) { _token[i].approve(address(_marginEngine), _amount[i]); } else { _token[i].approve(address(_wrapper[i]), _amount[i]); uint256 amount = _wrapper[i].deposit(_amount[i]); _wrapper[i].approve(address(_marginEngine), amount); } unchecked { ++i; } } _marginEngine.batchExecute(_batch); } function _assertFundAdmin() internal view virtual { if (!authority.doesUserHaveRole(msg.sender, Role.System_FundAdmin)) revert Unauthorized(); } /** * @notice Settles a single bid * @param _marginEngine to transact against * @param _bid is the signed data type containing bid information * @param _collaterals array of erc20 token addresses needed to collateralize options * @param _amounts array of (counterparty) deposit amounts for each collateral + premium (if applicable) */ function settleOnBehalfOf( IMarginEngine _marginEngine, Bid calldata _bid, address[] calldata _collaterals, uint256[] calldata _amounts, address _onBehalfOf ) external nonReentrant { _assertFundAdmin(); _settle(_marginEngine, _bid, _collaterals, _amounts, _onBehalfOf, false); } /** * @notice Settles a single bid * @param _marginEngine to transact against * @param _bid is the signed data type containing bid information * @param _collaterals array of erc20 token addresses needed to collateralize options * @param _amounts array of (counterparty) deposit amounts for each collateral + premium (if applicable) */ function settle(IMarginEngine _marginEngine, Bid calldata _bid, address[] calldata _collaterals, uint256[] calldata _amounts) external nonReentrant { // verify if seller is vault, will need to be fixed when Account Abstraction gets adopted bool isVault = _bid.vault.code.length > 0; if (isVault) IAuctionVault(_bid.vault).verifyOptions(_bid.options); _settle(_marginEngine, _bid, _collaterals, _amounts, msg.sender, isVault); } function _settle( IMarginEngine _marginEngine, Bid calldata _bid, address[] calldata _collaterals, uint256[] calldata _amounts, address _onBehalfOf, bool _isVault ) internal { _assertBidValid(_bid); bool isCashSettled = address(_marginEngine) == ME_CASH; // deposit actions from counterparty ActionArgs[] memory bActions = _createDeposits(_collaterals, _amounts, _onBehalfOf, _marginEngine); // mint or transfer actions from vault/margin account (ActionArgs[] memory sActions, ActionArgs[] memory bMints) = _createMintsOrTransfers(_bid.vault, _onBehalfOf, _bid.options, _bid.weights, isCashSettled, _isVault); bActions = bActions.concat(bMints); // premium transfer if (_bid.premium != 0) { ActionArgs memory premiumAction = _createPremiumTransfer(_bid.vault, _bid.premiumId, _bid.premium, isCashSettled); if (_bid.premium > 0) bActions = bActions.append(premiumAction); else sActions = sActions.append(premiumAction); } BatchExecute[] memory batch; // batch execute vault actions if (sActions.length > 0) batch = batch.append(BatchExecute(_bid.vault, sActions)); // batch execute counterparty actions if (bActions.length > 0) batch = batch.append(BatchExecute(_onBehalfOf, bActions)); emit SettledBid(_bid.nonce, _bid.vault, _onBehalfOf); _marginEngine.batchExecute(batch); } function settleBatchOnBehalfOf( IMarginEngine _marginEngine, Bid[] calldata _bids, address[] calldata _collaterals, uint256[] calldata _amounts, address _onBehalfOf ) external nonReentrant { _assertFundAdmin(); _settleBatch(_marginEngine, _bids, _collaterals, _amounts, _onBehalfOf); } /** * @notice Settles a several bids * @param _marginEngine to transact against * @param _bids is array of signed data types containing bid information * @param _collaterals array of erc20 token addresses needed to collateralize options * @param _amounts array of (counterparty) deposit amounts for each collateral + premium (if applicable) */ function settleBatch( IMarginEngine _marginEngine, Bid[] calldata _bids, address[] calldata _collaterals, uint256[] calldata _amounts ) external nonReentrant { _settleBatch(_marginEngine, _bids, _collaterals, _amounts, msg.sender); } function _settleBatch( IMarginEngine _marginEngine, Bid[] calldata _bids, address[] calldata _collaterals, uint256[] calldata _amounts, address _onBehalfOf ) internal { // deposit actions from counterparty ActionArgs[] memory depositActions = _createDeposits(_collaterals, _amounts, _onBehalfOf, _marginEngine); (BatchExecute[] memory batch, ActionArgs[] memory bActions) = _setupBidActionsBulk(_marginEngine, _bids, _onBehalfOf); // batch execute counterparty actions if (depositActions.length > 0 || bActions.length > 0) { batch = batch.append(BatchExecute(_onBehalfOf, depositActions.concat(bActions))); } _marginEngine.batchExecute(batch); } /*/////////////////////////////////////////////////////////////// View Functions //////////////////////////////////////////////////////////////*/ function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : _computeDomainSeparator(); } /*/////////////////////////////////////////////////////////////// Internal Functions //////////////////////////////////////////////////////////////*/ /** * @notice Bulk created bid related actions (verification of options, mints, premium transfers) */ function _setupBidActionsBulk(IMarginEngine _marginEngine, Bid[] calldata _bids, address _onBehalfOf) internal returns (BatchExecute[] memory batch, ActionArgs[] memory bActions) { uint256[] memory nonces = new uint256[](_bids.length); address[] memory vaults = new address[](_bids.length); bool isCashSettled = address(_marginEngine) == ME_CASH; for (uint256 i; i < _bids.length;) { _assertBidValid(_bids[i]); bool isVault; if (_onBehalfOf == msg.sender) { // verify if seller is vault, will need to be fixed when Account Abstraction gets adopted isVault = _bids[i].vault.code.length > 0; if (isVault) IAuctionVault(_bids[i].vault).verifyOptions(_bids[i].options); } // mint or transfer actions from vault/margin account (ActionArgs[] memory sActions, ActionArgs[] memory bMints) = _createMintsOrTransfers(_bids[i].vault, _onBehalfOf, _bids[i].options, _bids[i].weights, isCashSettled, isVault); if (bMints.length > 0) bActions = bActions.concat(bMints); // premium transfer if (_bids[i].premium != 0) { ActionArgs memory premiumAction = _createPremiumTransfer(_bids[i].vault, _bids[i].premiumId, _bids[i].premium, isCashSettled); if (_bids[i].premium > 0) bActions = bActions.append(premiumAction); else sActions = sActions.append(premiumAction); } // batch execute vault actions if (sActions.length > 0) batch = batch.append(BatchExecute(_bids[i].vault, sActions)); nonces[i] = _bids[i].nonce; vaults[i] = _bids[i].vault; unchecked { ++i; } } emit SettledBids(nonces, vaults, _onBehalfOf); } /** * @notice Only callable by Fund Admin from the settleBatchOnBehalfOf function * @dev Skipping bid verification, assumes all sellers have no code */ function _setupBidActionsBulkOnBehalfOf(IMarginEngine _marginEngine, Bid[] calldata _bids, address _onBehalfOf) internal returns (BatchExecute[] memory batch, ActionArgs[] memory bActions) { uint256 bidCount = _bids.length; uint256[] memory nonces = new uint256[](bidCount); address[] memory vaults = new address[](bidCount); bool isCashSettled = address(_marginEngine) == ME_CASH; for (uint256 i; i < bidCount;) { _assertBidValid(_bids[i]); // mint or transfer actions from vault/margin account (ActionArgs[] memory sActions, ActionArgs[] memory bMints) = _createMintsOrTransfers(_bids[i].vault, _onBehalfOf, _bids[i].options, _bids[i].weights, isCashSettled, false); if (bMints.length > 0) bActions = bActions.concat(bMints); // premium transfer if (_bids[i].premium != 0) { ActionArgs memory premiumAction = _createPremiumTransfer(_bids[i].vault, _bids[i].premiumId, _bids[i].premium, isCashSettled); if (_bids[i].premium > 0) bActions = bActions.append(premiumAction); else sActions = sActions.append(premiumAction); } // batch execute vault actions if (sActions.length > 0) batch = batch.append(BatchExecute(_bids[i].vault, sActions)); nonces[i] = _bids[i].nonce; vaults[i] = _bids[i].vault; unchecked { ++i; } } emit SettledBids(nonces, vaults, _onBehalfOf); } /** * @notice Helper function to transfer premium action * @dev Assumes premium payer has collateral in margin account * @return action encoded transfer instruction */ function _createPremiumTransfer(address _to, uint8 _premiumId, int256 _premium, bool _isCashSettled) internal view returns (ActionArgs memory) { if (_premium < 0) { _to = msg.sender; _premium *= -1; } return ActionArgs({ action: _isCashSettled ? CASH_TRANSFER_COLLATERAL_ACTION : PHYSICAL_TRANSFER_COLLATERAL_ACTION, data: abi.encode(uint80(uint256(_premium)), _to, _premiumId) }); } /** * @notice Helper function to setup deposit collateral actions * @dev Assumes has collateral in margin account * @return actions array of collateral deposits for counterparty */ function _createDeposits( address[] memory _collaterals, uint256[] memory _amounts, address _onBehalfOf, IMarginEngine _marginEngine ) internal returns (ActionArgs[] memory actions) { if (_collaterals.length == 0) return actions; if (_collaterals.length != _amounts.length) revert LengthMismatch(); bool isCashSettled = address(_marginEngine) == ME_CASH; IAssetRegistry assetRegistry = isCashSettled ? _marginEngine.grappa() : _marginEngine.pomace(); actions = new ActionArgs[](_collaterals.length); for (uint256 i; i < _collaterals.length;) { (address wrapper, uint256 amount) = _wrapToken(_onBehalfOf, _collaterals[i], _amounts[i], isCashSettled); uint8 collateralId = assetRegistry.assetIds(wrapper); actions[i] = ActionArgs({action: ADD_COLLATERAL_ACTION, data: abi.encode(address(this), uint80(amount), collateralId)}); unchecked { ++i; } } } /** * @notice Helper function to setup mint options action * @return vault array of option mints for vault * @return counterparty array of option mints for counterparty */ function _createMintsOrTransfers( address _vault, address _counterparty, uint256[] memory _options, int256[] memory _weights, bool _isCashSettled, bool _isVault ) internal pure returns (ActionArgs[] memory vault, ActionArgs[] memory counterparty) { unchecked { if (_options.length != _weights.length) revert LengthMismatch(); uint8 counterpartyAction; uint8 vaultAction; if (_isCashSettled) { counterpartyAction = CASH_MINT_LONG_INTO_ACCOUNT_ACTION; vaultAction = _isVault ? CASH_MINT_LONG_INTO_ACCOUNT_ACTION : CASH_TRANSFER_LONG_ACTION; } else { counterpartyAction = PHYSICAL_MINT_LONG_INTO_ACCOUNT_ACTION; vaultAction = _isVault ? PHYSICAL_MINT_LONG_INTO_ACCOUNT_ACTION : PHYSICAL_TRANSFER_LONG_ACTION; } for (uint256 i; i < _options.length; ++i) { int256 weight = _weights[i]; if (weight == 0) continue; // counterparty receives negative weighted instruments (vault is short) // vault receives positive weighted instruments (vault long) if (weight < 0) { vault = vault.append( ActionArgs({action: vaultAction, data: abi.encode(_options[i], _counterparty, uint64(uint256(-weight)))}) ); } else { counterparty = counterparty.append( ActionArgs({action: counterpartyAction, data: abi.encode(_options[i], _vault, uint64(uint256(weight)))}) ); } } } } /** * @notice Wraps asset on the fly */ function _wrapToken(address _from, address _underlying, uint256 _amount, bool _isCashSettled) internal returns (address wrapper, uint256 amount) { IERC20 underlying = IERC20(_underlying); address marginEngine = _isCashSettled ? ME_CASH : ME_PHYSICAL; // Transfer underlying to this contract if (_from != address(this)) underlying.safeTransferFrom(_from, address(this), _amount); wrapper = wrapToken[_underlying]; // if _underlying has no wrapper, then skip wrapping if (wrapper == address(0)) { underlying.approve(marginEngine, _amount); return (_underlying, _amount); } // Approve wrapper to transfer underlying to itself from this contract underlying.approve(wrapper, _amount); IHnToken hnToken = IHnToken(wrapper); // deposits underlying to wrapper amount = hnToken.deposit(_amount); // Approving margin engine to pull wrapped token from this contract hnToken.approve(marginEngine, amount); } /** * @notice Asserts signatory on the data */ function _assertBidValid(Bid calldata _bid) internal { if (_bid.expiry <= block.timestamp) revert ExpiredBid(); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Bid(address vault,int256[] weights,uint256[] options,uint8 premiumId,int256 premium,uint256 expiry,uint256 nonce)" ), _bid.vault, keccak256(abi.encodePacked(_bid.weights)), keccak256(abi.encodePacked(_bid.options)), _bid.premiumId, _bid.premium, _bid.expiry, _bid.nonce ) ) ) ), _bid.v, _bid.r, _bid.s ); if (recoveredAddress == address(0) || recoveredAddress != owner()) revert Unauthorized(); if (noncesUsed[_bid.nonce]) revert NonceAlreadyUsed(); noncesUsed[_bid.nonce] = true; } } function _computeDomainSeparator() internal view returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256("Hn Simple Settlement"), keccak256("3"), block.chainid, address(this) ) ); } /*/////////////////////////////////////////////////////////////// Override Upgrade Permission //////////////////////////////////////////////////////////////*/ /** * @dev Upgradable by the owner. * */ function _authorizeUpgrade(address /*newImplementation*/ ) internal view override { _checkOwner(); } /** * @notice overrides the default _checkOwner function to revert with Unauthorized error */ function _checkOwner() internal view override { if (owner() != _msgSender()) revert Unauthorized(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.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' 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)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ 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"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to * 0 before setting it to a non-zero value. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; import "../../interfaces/draft-IERC1822.sol"; import "../ERC1967/ERC1967Upgrade.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeTo(address newImplementation) public virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; /** * @title IHnToken * @notice Interface for Hn tokens */ interface IHnToken is IERC20 { function deposit(uint256 _amount) external returns (uint256 amount); function burn(uint256 _amount, string memory _recipient) external; function burnFor(address _owner, uint256 _amount, string memory _recipient, uint8 _v, bytes32 _r, bytes32 _s) external; function withdrawTo(address _recipient, uint256 _amount, uint8 _v, bytes32 _r, bytes32 _s) external returns (uint256 amount); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; /** * @title IAssetRegistry * @notice Interface for the registry contract to provide compatibility between Pomace and Grappa */ interface IAssetRegistry { function assets(uint8 _id) external view returns (address addr, uint8 decimals); function assetIds(address _asset) external view returns (uint8 id); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; /** * @notice Interface for the abstract auction vault contract which handles both cash and physical settlement * used only in the settlement contracts to provide compatibility between the vault interfaces */ interface IAuctionVault { /// @notice verifies the options are allowed to be minted /// @param _options to mint function verifyOptions(uint256[] calldata _options) external view; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import {IAssetRegistry} from "./IAssetRegistry.sol"; import "../config/types.sol"; /** * @notice Interface for the abstract margin engine contract which handles both cash and physical settlement * used only in the settlement contracts to provide compatibility between the engine interfaces */ interface IMarginEngine { function optionToken() external view returns (address); function marginAccounts(address) external view returns (Position[] memory shorts, Position[] memory longs, Balance[] memory collaterals); function previewMinCollateral(Position[] memory shorts, Position[] memory longs) external view returns (Balance[] memory); function allowedExecutionLeft(uint160 mask, address account) external view returns (uint256); function setAccountAccess(address account, uint256 allowedExecutions) external; function revokeSelfAccess(address granter) external; function grappa() external view returns (IAssetRegistry grappa); function pomace() external view returns (IAssetRegistry pomace); function execute(address account, ActionArgs[] calldata actions) external; function batchExecute(BatchExecute[] calldata batchActions) external; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.0; import "../config/enums.sol"; /// @notice A generic interface for a contract which provides authorization data to an Auth instance. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol) /// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol) interface IAuthority { function canCall(address user, address target, bytes4 functionSig) external view returns (bool); function doesUserHaveRole(address user, Role role) external view returns (bool); function getUserRoles(address user) external view returns (bytes32); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; import "../config/constants.sol"; import "../config/types.sol"; /** * @dev implements same functions for the management of ActionArgs[] as ActionUtil libs in core-cash and core-physical repositories */ library ActionUtil { function concat(ActionArgs[] memory x, ActionArgs[] memory v) internal pure returns (ActionArgs[] memory y) { y = new ActionArgs[](x.length + v.length); uint256 z; uint256 i; for (i; i < x.length;) { y[z] = x[i]; unchecked { ++z; ++i; } } for (i = 0; i < v.length;) { y[z] = v[i]; unchecked { ++z; ++i; } } } function append(ActionArgs[] memory x, ActionArgs memory v) internal pure returns (ActionArgs[] memory y) { y = new ActionArgs[](x.length + 1); uint256 i; for (i; i < x.length;) { y[i] = x[i]; unchecked { ++i; } } y[i] = v; } function append(BatchExecute[] memory x, BatchExecute memory v) internal pure returns (BatchExecute[] memory y) { y = new BatchExecute[](x.length + 1); uint256 i; for (i; i < x.length;) { y[i] = x[i]; unchecked { ++i; } } y[i] = v; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; struct Bid { // vault selling structures address vault; // Indicated how much the vault is short or long this instrument in a structure int256[] weights; // option ids uint256[] options; // id of the asset uint8 premiumId; // premium paid to vault int256 premium; // expiration of bid uint256 expiry; // Number only used once uint256 nonce; // Signature recovery id uint8 v; // r portion of the ECSDA signature bytes32 r; // s portion of the ECSDA signature bytes32 s; } /** * @dev Position struct * @param tokenId option token id * @param amount number option tokens */ struct Position { uint256 tokenId; uint64 amount; } /** * @dev struct representing the current balance for a given collateral * @param collateralId asset id * @param amount amount the asset */ struct Balance { uint8 collateralId; uint80 amount; } struct Collateral { // Grappa asset Id uint8 id; // ERC20 token address for the required collateral address addr; // the amount of decimals or token uint8 decimals; } /** * @notice The action type for the execute function * @dev unitary representation of the ActionArgs struct from the core physical and cash engines */ struct ActionArgs { // action type represented as uint8 (see enum ActionType) uint8 action; // data payload for the action bytes data; } /** * @notice The batch action type for the execute function * @dev unitary representation of the BatchExecute struct from the core physical and cash engines */ struct BatchExecute { // address of the account to execute the batch address subAccount; // array of actions to execute ActionArgs[] actions; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; error BadAddress(); error BadAmount(); error LengthMismatch(); error NonceAlreadyUsed(); error Unauthorized(); error ExpiredBid();
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; /** * @dev common action types on margin engines * these constants are defined to add compatibility between ActionTypes of physical and cash settled margin engines * uint8 values correspond to the order (and value) of the enum entries */ // actions that are aligned in both enums and use the same uint8 representation between engines uint8 constant ADD_COLLATERAL_ACTION = 0; uint8 constant REMOVE_COLLATERAL_ACTION = 1; uint8 constant MINT_SHORT_ACTION = 2; uint8 constant BURN_SHORT_ACTION = 3; // actions that have misaligned order in enums of physical and cash engines uint8 constant PHYSICAL_ADD_LONG_ACTION = 4; uint8 constant CASH_ADD_LONG_ACTION = 6; uint8 constant PHYSICAL_REMOVE_LONG_ACTION = 5; uint8 constant CASH_REMOVE_LONG_ACTION = 7; uint8 constant PHYSICAL_SETTLE_ACCOUNT_ACTION = 7; uint8 constant CASH_SETTLE_ACCOUNT_ACTION = 8; uint8 constant PHYSICAL_MINT_LONG_INTO_ACCOUNT_ACTION = 8; // increase short (debt) position in one subAccount, increase long token directly to another subAccount uint8 constant CASH_MINT_LONG_INTO_ACCOUNT_ACTION = 9; // increase short (debt) position in one subAccount, increase long token directly to another subAccount uint8 constant PHYSICAL_TRANSFER_COLLATERAL_ACTION = 9; // transfer collateral directly to another subAccount uint8 constant CASH_TRANSFER_COLLATERAL_ACTION = 10; // transfer collateral directly to another subAccount uint8 constant PHYSICAL_TRANSFER_LONG_ACTION = 10; // transfer long directly to another subAccount uint8 constant CASH_TRANSFER_LONG_ACTION = 11; // transfer long directly to another subAccount uint8 constant PHYSICAL_TRANSFER_SHORT_ACTION = 11; uint8 constant CASH_TRANSFER_SHORT_ACTION = 12; // additional action that is only used in the physical engine: uint8 constant EXERCISE_TOKEN_ACTION = 6; uint256 constant UNIT = 1e6;
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/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"); (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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/IERC1967.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ */ abstract contract ERC1967Upgrade is IERC1967 { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; enum Role { Investor_MFFeederDomestic, Investor_MFFeederInternational, Investor_SDYFDomestic, Investor_SDYFInternational, Investor_LOFDomestic, Investor_LOFInternational, Investor_Reserve1, Investor_Reserve2, Investor_Reserve3, Investor_Reserve4, Investor_Reserve5, Custodian_Centralized, Custodian_Decentralized, System_FundAdmin, System_Token, System_Vault, System_Auction, System_Teller, System_Oracle, System_MarginEngine, LiquidityProvider_Options, LiquidityProvider_Spot }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/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"); (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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
{ "remappings": [ "forge-std/=lib/forge-std/src/", "solmate/=lib/solmate/src/", "openzeppelin/=lib/openzeppelin-contracts/contracts/", "openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "cm-cash-engine/=lib/cross-margin-engine/src/settled-cash/", "cm-physical-engine/=lib/cross-margin-engine/src/settled-physical/", "grappa/=lib/cross-margin-engine/lib/core-cash/src/", "pomace/=lib/cross-margin-engine/lib/core-physical/src/", "grappa-test/=lib/cross-margin-engine/lib/core-cash/test/", "pomace-test/=lib/cross-margin-engine/lib/core-physical/test/", "coins/=lib/coins/src/", "entitlements/=lib/entitlements/", "@openzeppelin/contracts-upgradeable/=lib/entitlements/lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/entitlements/lib/openzeppelin-contracts/contracts/", "array-lib/=lib/cross-margin-engine/lib/array-lib/src/", "bpb-dateTime/=lib/coins/lib/BokkyPooBahsDateTimeLibrary/contracts/", "core-cash/=lib/cross-margin-engine/lib/core-cash/", "core-physical/=lib/cross-margin-engine/lib/core-physical/", "cross-margin-engine/=lib/cross-margin-engine/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 10000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_meCash","type":"address"},{"internalType":"address","name":"_mePhysical","type":"address"},{"internalType":"address","name":"_authority","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BadAddress","type":"error"},{"inputs":[],"name":"BadAmount","type":"error"},{"inputs":[],"name":"ExpiredBid","type":"error"},{"inputs":[],"name":"LengthMismatch","type":"error"},{"inputs":[],"name":"NonceAlreadyUsed","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"counterparty","type":"address"}],"name":"SettledBid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"nonces","type":"uint256[]"},{"indexed":false,"internalType":"address[]","name":"vaults","type":"address[]"},{"indexed":true,"internalType":"address","name":"counterparty","type":"address"}],"name":"SettledBids","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":false,"internalType":"address","name":"token1","type":"address"}],"name":"TokenMapSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ME_CASH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ME_PHYSICAL","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract IAuthority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_marginEngine","type":"address"},{"internalType":"uint8","name":"_collateralId","type":"uint8"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"string","name":"_recipient","type":"string"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_marginEngine","type":"address"},{"internalType":"uint8","name":"_collateralId","type":"uint8"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"string","name":"_recipient","type":"string"},{"internalType":"address","name":"_onBehalfOf","type":"address"}],"name":"burnOnBehalfOf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint8","name":"_collateralId","type":"uint8"},{"internalType":"uint256","name":"_collateralAmount","type":"uint256"}],"name":"exercise","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"noncesUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_marginEngine","type":"address"},{"internalType":"address[]","name":"_subAccounts","type":"address[]"}],"name":"revokeMarginAccountAccess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token0","type":"address"},{"internalType":"address","name":"_token1","type":"address"}],"name":"setTokenMap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IMarginEngine","name":"_marginEngine","type":"address"},{"components":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"int256[]","name":"weights","type":"int256[]"},{"internalType":"uint256[]","name":"options","type":"uint256[]"},{"internalType":"uint8","name":"premiumId","type":"uint8"},{"internalType":"int256","name":"premium","type":"int256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Bid","name":"_bid","type":"tuple"},{"internalType":"address[]","name":"_collaterals","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"settle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IMarginEngine","name":"_marginEngine","type":"address"},{"components":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"int256[]","name":"weights","type":"int256[]"},{"internalType":"uint256[]","name":"options","type":"uint256[]"},{"internalType":"uint8","name":"premiumId","type":"uint8"},{"internalType":"int256","name":"premium","type":"int256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Bid[]","name":"_bids","type":"tuple[]"},{"internalType":"address[]","name":"_collaterals","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"settleBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IMarginEngine","name":"_marginEngine","type":"address"},{"internalType":"address[]","name":"_from","type":"address[]"},{"internalType":"contract IERC20[]","name":"_token","type":"address[]"},{"internalType":"uint256[]","name":"_amount","type":"uint256[]"},{"internalType":"contract IHnToken[]","name":"_wrapper","type":"address[]"},{"components":[{"internalType":"address","name":"subAccount","type":"address"},{"components":[{"internalType":"uint8","name":"action","type":"uint8"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct ActionArgs[]","name":"actions","type":"tuple[]"}],"internalType":"struct BatchExecute[]","name":"_batch","type":"tuple[]"}],"name":"settleBatchFundAdminOnly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IMarginEngine","name":"_marginEngine","type":"address"},{"components":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"int256[]","name":"weights","type":"int256[]"},{"internalType":"uint256[]","name":"options","type":"uint256[]"},{"internalType":"uint8","name":"premiumId","type":"uint8"},{"internalType":"int256","name":"premium","type":"int256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Bid[]","name":"_bids","type":"tuple[]"},{"internalType":"address[]","name":"_collaterals","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address","name":"_onBehalfOf","type":"address"}],"name":"settleBatchOnBehalfOf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IMarginEngine","name":"_marginEngine","type":"address"},{"components":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"int256[]","name":"weights","type":"int256[]"},{"internalType":"uint256[]","name":"options","type":"uint256[]"},{"internalType":"uint8","name":"premiumId","type":"uint8"},{"internalType":"int256","name":"premium","type":"int256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Bid","name":"_bid","type":"tuple"},{"internalType":"address[]","name":"_collaterals","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address","name":"_onBehalfOf","type":"address"}],"name":"settleOnBehalfOf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"unWrapToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_marginEngine","type":"address"},{"internalType":"uint8","name":"_collateralId","type":"uint8"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_marginEngine","type":"address"},{"internalType":"uint8","name":"_collateralId","type":"uint8"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"},{"internalType":"address","name":"_onBehalfOf","type":"address"}],"name":"withdrawOnBehalfOf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_marginEngine","type":"address"},{"internalType":"address","name":"_subAccount","type":"address"},{"internalType":"uint8","name":"_collateralId","type":"uint8"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"wrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IMarginEngine","name":"_marginEngine","type":"address"},{"internalType":"address","name":"_subAccount","type":"address"},{"internalType":"uint8","name":"_fromId","type":"uint8"},{"internalType":"address","name":"_toToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"wrapTo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wrapToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
610140604052306080523480156200001657600080fd5b5060405162005f0838038062005f088339810160408190526200003991620002a1565b600054610100900460ff16158080156200005a5750600054600160ff909116105b806200008a575062000077306200027560201b6200214d1760201c565b1580156200008a575060005460ff166001145b620000f25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff19166001179055801562000116576000805461ff0019166101001790555b6001600160a01b03841615806200013457506001600160a01b038316155b806200014757506001600160a01b038216155b1562000166576040516332691b5760e01b815260040160405180910390fd5b4660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527fc66e37d5f583a79f144e1590643945b3f19d4d1f4c4324cd9bcac64fd93e5f09828401527f2a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de6060830152608082019490945230818401528151808203909301835260c0019052805191012060c0526001600160a01b0380851660e0528381166101005282166101205280156200026b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050620002eb565b6001600160a01b03163b151590565b80516001600160a01b03811681146200029c57600080fd5b919050565b600080600060608486031215620002b757600080fd5b620002c28462000284565b9250620002d26020850162000284565b9150620002e26040850162000284565b90509250925092565b60805160a05160c05160e0516101005161012051615b64620003a4600039600081816104950152612a9d0152600081816102b8015281816111aa0152612f8a0152600081816104e9015281816114710152818161190d015281816121be015281816126ea01528181612b5901528181612fb0015281816138a60152614252015260006107b5015260006106e00152600081816107e10152818161087c015281816109b501528181610a4b0152610b460152615b646000f3fe6080604052600436106101b75760003560e01c80638da5cb5b116100ec578063c4d66de81161008a578063ee74885011610064578063ee7488501461052b578063eeed714814610561578063f2fde38b14610581578063fe01903d146105a157600080fd5b8063c4d66de8146104b7578063d108d194146104d7578063d1e96fc81461050b57600080fd5b8063b0fdab85116100c6578063b0fdab851461040d578063b54aa8be1461042d578063bccab1c614610463578063bf7e214f1461048357600080fd5b80638da5cb5b146103af578063a6f6f540146103cd578063a82b566c146103ed57600080fd5b80634281c53e116101595780637042853d116101335780637042853d1461033a578063715018a61461035a578063808553b91461036f57806385b522ed1461038f57600080fd5b80634281c53e146102f25780634f1ef2861461031257806352d1902d1461032557600080fd5b806331f111eb1161019557806331f111eb146102435780633644e515146102635780633659cfe6146102865780633759cace146102a657600080fd5b80630f6f1c83146101bc5780631414d6d61461020157806320aff42814610223575b600080fd5b3480156101c857600080fd5b506101ec6101d7366004614a10565b60976020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b34801561020d57600080fd5b5061022161021c366004614a4d565b6105c1565b005b34801561022f57600080fd5b5061022161023e366004614ab2565b6105ea565b34801561024f57600080fd5b5061022161025e366004614b34565b6106c7565b34801561026f57600080fd5b506102786106dc565b6040519081526020016101f8565b34801561029257600080fd5b506102216102a1366004614ba7565b6107d7565b3480156102b257600080fd5b506102da7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101f8565b3480156102fe57600080fd5b5061022161030d366004614bcb565b610979565b610221610320366004614d3f565b6109ab565b34801561033157600080fd5b50610278610b39565b34801561034657600080fd5b50610221610355366004614dfd565b610bfe565b34801561036657600080fd5b50610221610cba565b34801561037b57600080fd5b5061022161038a3660046150a6565b610cce565b34801561039b57600080fd5b506102216103aa36600461519e565b61119e565b3480156103bb57600080fd5b506033546001600160a01b03166102da565b3480156103d957600080fd5b506102216103e83660046151dd565b611466565b3480156103f957600080fd5b5061027861040836600461521e565b6118f7565b34801561041957600080fd5b50610221610428366004615282565b611db6565b34801561043957600080fd5b506102da610448366004614ba7565b6099602052600090815260409020546001600160a01b031681565b34801561046f57600080fd5b5061022161047e3660046152d7565b611e7c565b34801561048f57600080fd5b506102da7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104c357600080fd5b506102216104d2366004614ba7565b611e92565b3480156104e357600080fd5b506102da7f000000000000000000000000000000000000000000000000000000000000000081565b34801561051757600080fd5b5061022161052636600461535c565b612053565b34801561053757600080fd5b506102da610546366004614ba7565b6098602052600090815260409020546001600160a01b031681565b34801561056d57600080fd5b5061022161057c366004615407565b612074565b34801561058d57600080fd5b5061022161059c366004614ba7565b6120a8565b3480156105ad57600080fd5b506102216105bc3660046154c7565b612135565b6105c961215c565b6105d8868686868686336121b5565b6105e26001606555565b505050505050565b6105f2612576565b6001600160a01b038216610632576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03828116600081815260986020908152604080832080549587167fffffffffffffffffffffffff00000000000000000000000000000000000000009687168117909155808452609983529281902080549095168417909455925190815290917fcd343f99315948a9186a773eab6d9017571a9be1337a150a1517555d16e28b6b910160405180910390a25050565b6106d58585858585336125ba565b5050505050565b60007f000000000000000000000000000000000000000000000000000000000000000046146107b2576107ad604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527fc66e37d5f583a79f144e1590643945b3f19d4d1f4c4324cd9bcac64fd93e5f09918101919091527f2a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de60608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361087a5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166108d57f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b0316146109515760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610871565b61095a816128c0565b60408051600080825260208201909252610976918391906128c8565b50565b61098161215c565b610989612a6d565b610998878787878787876121b5565b6109a26001606555565b50505050505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610a495760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401610871565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610aa47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614610b205760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610871565b610b29826128c0565b610b35828260016128c8565b5050565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610bd95760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610871565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b610c0661215c565b600080610c166020880188614ba7565b6001600160a01b03163b1190508015610c9f57610c366020870187614ba7565b6001600160a01b031663a06eb657610c516040890189615574565b6040518363ffffffff1660e01b8152600401610c6e9291906155dc565b60006040518083038186803b158015610c8657600080fd5b505afa158015610c9a573d6000803e3d6000fd5b505050505b610caf8787878787873388612b4c565b506105e26001606555565b610cc2612576565b610ccc6000612e8c565b565b610cd6612a6d565b60005b8681101561111a57308a8a83818110610cf457610cf461562e565b9050602002016020810190610d099190614ba7565b6001600160a01b031614610d9357610d938a8a83818110610d2c57610d2c61562e565b9050602002016020810190610d419190614ba7565b30888885818110610d5457610d5461562e565b905060200201358b8b86818110610d6d57610d6d61562e565b9050602002016020810190610d829190614ba7565b6001600160a01b0316929190612ef6565b6000848483818110610da757610da761562e565b9050602002016020810190610dbc9190614ba7565b6001600160a01b031603610ea857878782818110610ddc57610ddc61562e565b9050602002016020810190610df19190614ba7565b6001600160a01b031663095ea7b38c888885818110610e1257610e1261562e565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b1681526001600160a01b03909416600485015260200291909101356024830152506044016020604051808303816000875af1158015610e7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea2919061565d565b50611112565b878782818110610eba57610eba61562e565b9050602002016020810190610ecf9190614ba7565b6001600160a01b031663095ea7b3858584818110610eef57610eef61562e565b9050602002016020810190610f049190614ba7565b888885818110610f1657610f1661562e565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b1681526001600160a01b03909416600485015260200291909101356024830152506044016020604051808303816000875af1158015610f82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa6919061565d565b506000848483818110610fbb57610fbb61562e565b9050602002016020810190610fd09190614ba7565b6001600160a01b031663b6b55f25888885818110610ff057610ff061562e565b905060200201356040518263ffffffff1660e01b815260040161101591815260200190565b6020604051808303816000875af1158015611034573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611058919061567f565b905084848381811061106c5761106c61562e565b90506020020160208101906110819190614ba7565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038e8116600483015260248201849052919091169063095ea7b3906044016020604051808303816000875af11580156110eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110f919061565d565b50505b600101610cd9565b506040517fc46c67fb0000000000000000000000000000000000000000000000000000000081526001600160a01b038b169063c46c67fb90611160908490600401615754565b600060405180830381600087803b15801561117a57600080fd5b505af115801561118e573d6000803e3d6000fd5b5050505050505050505050505050565b6111a661215c565b60007f000000000000000000000000000000000000000000000000000000000000000090506000816001600160a01b03166307af09266040518163ffffffff1660e01b8152600401602060405180830381865afa15801561120b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122f91906157ef565b6040517f1b3accac00000000000000000000000000000000000000000000000000000000815260ff861660048201526001600160a01b039190911690631b3accac906024016040805180830381865afa158015611290573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b4919061580c565b5090506112cc6001600160a01b038216333086612ef6565b60408051600280825260608201909252600091816020015b6040805180820190915260008152606060208201528152602001906001900390816112e4579050506040805180820182526000815281513060208281019190915292810188905260ff891660608201529293509190820190608001604051602081830303815290604052815250816000815181106113645761136461562e565b60200260200101819052506040518060400160405280600660ff16815260200188886040516020016113aa92919091825267ffffffffffffffff16602082015260400190565b604051602081830303815290604052815250816001815181106113cf576113cf61562e565b60209081029190910101526040517f8e1b5c0e0000000000000000000000000000000000000000000000000000000081526001600160a01b03841690638e1b5c0e90611421903390859060040161583b565b600060405180830381600087803b15801561143b57600080fd5b505af115801561144f573d6000803e3d6000fd5b505050505050506114606001606555565b50505050565b61146e61215c565b837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b039081169082161460008161150d57826001600160a01b03166307af09266040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114e4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150891906157ef565b61156f565b826001600160a01b031663473f5adb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561154b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156f91906157ef565b60408051600180825281830190925291925060009190816020015b60408051808201909152600081526060602082015281526020019060019003908161158a5790505060408051808201825260018152815169ffffffffffffffffffff8916602082810191909152309382019390935260ff8a1660608201529293509190820190608001604051602081830303815290604052815250816000815181106116185761161861562e565b60209081029190910101526040517f8e1b5c0e0000000000000000000000000000000000000000000000000000000081526001600160a01b03851690638e1b5c0e9061166a908a90859060040161583b565b600060405180830381600087803b15801561168457600080fd5b505af1158015611698573d6000803e3d6000fd5b50506040517f1b3accac00000000000000000000000000000000000000000000000000000000815260ff89166004820152600092506001600160a01b0385169150631b3accac906024016040805180830381865afa1580156116fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611722919061580c565b50905060008061173430848a89612f7e565b90925090506001600160a01b038216611779576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fd8e8dbc70000000000000000000000000000000000000000000000000000000081526001600160a01b03838116600483015286169063d8e8dbc790602401602060405180830381865afa1580156117d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117fc919061585d565b6040805180820182526000815281513060208281019190915269ffffffffffffffffffff86169382019390935260ff84166060820152929b509190820190608001604051602081830303815290604052815250846000815181106118625761186261562e565b60209081029190910101526040517f8e1b5c0e0000000000000000000000000000000000000000000000000000000081526001600160a01b03881690638e1b5c0e906118b4908d90889060040161583b565b600060405180830381600087803b1580156118ce57600080fd5b505af11580156118e2573d6000803e3d6000fd5b50505050505050505050506114606001606555565b600061190161215c565b611909612a6d565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316876001600160a01b0316146119ab57866001600160a01b03166307af09266040518163ffffffff1660e01b8152600401602060405180830381865afa158015611982573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a691906157ef565b611a0d565b866001600160a01b031663473f5adb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119e9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0d91906157ef565b6040517fd8e8dbc70000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152919091169063d8e8dbc790602401602060405180830381865afa158015611a6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a92919061585d565b90508060ff16600003611ad1576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001808252818301909252600091816020015b604080518082019091526000815260606020820152815260200190600190039081611ae85790505060408051808201825260018152815169ffffffffffffffffffff8816602082810191909152309382019390935260ff8a166060820152929350919082019060800160405160208183030381529060405281525081600081518110611b7657611b7661562e565b60209081029190910101526040517f8e1b5c0e0000000000000000000000000000000000000000000000000000000081526001600160a01b03891690638e1b5c0e90611bc8908a90859060040161583b565b600060405180830381600087803b158015611be257600080fd5b505af1158015611bf6573d6000803e3d6000fd5b50506040517fb6b55f25000000000000000000000000000000000000000000000000000000008152600481018790526001600160a01b038816925063b6b55f2591506024016020604051808303816000875af1158015611c5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c7e919061567f565b925082600003611cba576040517f749b593900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820182526000815281513060208281019190915269ffffffffffffffffffff87169382019390935260ff85166060820152909182019060800160405160208183030381529060405281525081600081518110611d1d57611d1d61562e565b60209081029190910101526040517f8e1b5c0e0000000000000000000000000000000000000000000000000000000081526001600160a01b03891690638e1b5c0e90611d6f908a90859060040161583b565b600060405180830381600087803b158015611d8957600080fd5b505af1158015611d9d573d6000803e3d6000fd5b505050505050611dad6001606555565b95945050505050565b611dbe612576565b8260005b828110156106d557816001600160a01b03166373d422af858584818110611deb57611deb61562e565b9050602002016020810190611e009190614ba7565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015611e5957600080fd5b505af1158015611e6d573d6000803e3d6000fd5b50505050806001019050611dc2565b611e84612a6d565b6105e28686868686866125ba565b600054610100900460ff1615808015611eb25750600054600160ff909116105b80611ecc5750303b158015611ecc575060005460ff166001145b611f3e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610871565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611f9c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6001600160a01b038216611fdc576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611fe582612e8c565b611fed613264565b8015610b3557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b61205b61215c565b612063612a6d565b610998878787878787876000612b4c565b61207c61215c565b612084612a6d565b61209488888888888888886132e1565b61209e6001606555565b5050505050505050565b6120b0612576565b6001600160a01b03811661212c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610871565b61097681612e8c565b61213d61215c565b61099887878787878787336132e1565b6001600160a01b03163b151590565b6002606554036121ae5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610871565b6002606555565b600087905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b03161461225c57816001600160a01b03166307af09266040518163ffffffff1660e01b8152600401602060405180830381865afa158015612233573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225791906157ef565b6122be565b816001600160a01b031663473f5adb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561229a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122be91906157ef565b6040517f1b3accac00000000000000000000000000000000000000000000000000000000815260ff8a1660048201529091506000906001600160a01b03831690631b3accac906024016040805180830381865afa158015612323573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612347919061580c565b506001600160a01b0380821660009081526099602052604090205491925016308161236f5750845b604080516001808252818301909252600091816020015b6040805180820190915260008152606060208201528152602001906001900390816123865790505090506040518060400160405280600160ff1681526020018c848f6040516020016124059392919069ffffffffffffffffffff9390931683526001600160a01b0391909116602083015260ff16604082015260600190565b6040516020818303038152906040528152508160008151811061242a5761242a61562e565b60209081029190910101526040517f8e1b5c0e0000000000000000000000000000000000000000000000000000000081526001600160a01b03871690638e1b5c0e9061247c908a90859060040161583b565b600060405180830381600087803b15801561249657600080fd5b505af11580156124aa573d6000803e3d6000fd5b505050506001600160a01b03831615612560576040517fc2930c450000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018d905260ff8c166044830152606482018b9052608482018a905285169063c2930c459060a4016020604051808303816000875af115801561253c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118e919061567f565b50505050505050505050505050565b6001606555565b6033546001600160a01b03163314610ccc576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001808252818301909252879160009190816020015b6040805180820190915260008152606060208201528152602001906001900390816125d45790505060408051808201825260018152815169ffffffffffffffffffff8a16602082810191909152309382019390935260ff8b1660608201529293509190820190608001604051602081830303815290604052815250816000815181106126625761266261562e565b60209081029190910101526040517f8e1b5c0e0000000000000000000000000000000000000000000000000000000081526001600160a01b03831690638e1b5c0e906126b4908690859060040161583b565b600060405180830381600087803b1580156126ce57600080fd5b505af11580156126e2573d6000803e3d6000fd5b5050505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b03161461278857826001600160a01b03166307af09266040518163ffffffff1660e01b8152600401602060405180830381865afa15801561275f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278391906157ef565b6127ea565b826001600160a01b031663473f5adb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ea91906157ef565b6040517f1b3accac00000000000000000000000000000000000000000000000000000000815260ff8a1660048201529091506000906001600160a01b03831690631b3accac906024016040805180830381865afa15801561284f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612873919061580c565b506040517f7641e6f30000000000000000000000000000000000000000000000000000000081529091506001600160a01b03821690637641e6f390611160908b908b908b9060040161587a565b610976612576565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612900576128fb8361343f565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561295a575060408051601f3d908101601f191682019092526129579181019061567f565b60015b6129cc5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152608401610871565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612a615760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608401610871565b506128fb838383613515565b6040517fea7ca2760000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ea7ca27690612ad5903390600d906004016158b0565b602060405180830381865afa158015612af2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b16919061565d565b610ccc576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b558761353a565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b03161490506000612c0188888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808c0282810182019093528b82529093508b92508a9182918501908490808284376000920191909152508992508f915061385d9050565b9050600080612caf612c1660208d018d614ba7565b87612c2460408f018f615574565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508e8060200190612c749190615574565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508b92508c9150613b739050565b9092509050612cbe8382613d54565b925060808b013515612d29576000612cfa612cdc60208e018e614ba7565b8d6060016020810190612cef9190615904565b8e6080013588613e6d565b905060008c608001351315612d1a57612d138482613f38565b9350612d27565b612d248382613f38565b92505b505b815160609015612d6f57612d6c60405180604001604052808e6000016020810190612d549190614ba7565b6001600160a01b031681526020018590528290614019565b90505b835115612da957612da66040518060400160405280896001600160a01b03168152602001868152508261401990919063ffffffff16565b90505b6001600160a01b038716612dc060208e018e614ba7565b6001600160a01b03167f977d0b17c986a7a0c40ce64bd03ac2f5e30e4a059d775ae65b34e51c38eb41538e60c00135604051612dfe91815260200190565b60405180910390a36040517fc46c67fb0000000000000000000000000000000000000000000000000000000081526001600160a01b038e169063c46c67fb90612e4b908490600401615754565b600060405180830381600087803b158015612e6557600080fd5b505af1158015612e79573d6000803e3d6000fd5b5050505050505050505050505050505050565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526114609085906140d5565b600080848184612fae577f0000000000000000000000000000000000000000000000000000000000000000612fd0565b7f00000000000000000000000000000000000000000000000000000000000000005b90506001600160a01b0388163014612ff757612ff76001600160a01b038316893089612ef6565b6001600160a01b03808816600090815260986020526040902054169350836130b3576040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526024820188905283169063095ea7b3906044016020604051808303816000875af1158015613081573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a5919061565d565b50868693509350505061325b565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526024820188905283169063095ea7b3906044016020604051808303816000875af115801561311b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061313f919061565d565b506040517fb6b55f250000000000000000000000000000000000000000000000000000000081526004810187905284906001600160a01b0382169063b6b55f25906024016020604051808303816000875af11580156131a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131c6919061567f565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152602482018390529195509082169063095ea7b3906044016020604051808303816000875af1158015613232573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613256919061565d565b505050505b94509492505050565b600054610100900460ff1661256f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610871565b600061335486868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152508792508e915061385d9050565b90506000806133658b8b8b876141bd565b9150915060008351118061337a575060008151115b156133bb576133b86040518060400160405280866001600160a01b031681526020016133af8487613d5490919063ffffffff16565b90528390614019565b91505b6040517fc46c67fb0000000000000000000000000000000000000000000000000000000081526001600160a01b038c169063c46c67fb90613400908590600401615754565b600060405180830381600087803b15801561341a57600080fd5b505af115801561342e573d6000803e3d6000fd5b505050505050505050505050505050565b6001600160a01b0381163b6134bc5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610871565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b61351e8361478b565b60008251118061352b5750805b156128fb5761146083836147cb565b428160a0013511613577576040517ff4732ca300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060016135836106dc565b7f32f9555cd4fc061398f70871cdfce12ed4137df14855f94c66900f5f71214eba6135b16020860186614ba7565b6135be6020870187615574565b6040516020016135cf929190615921565b604051602081830303815290604052805190602001208680604001906135f59190615574565b604051602001613606929190615950565b60408051601f19818403018152919052805160209091012061362e6080890160608a01615904565b88608001358960a001358a60c001356040516020016136919897969594939291909788526001600160a01b039690961660208801526040870194909452606086019290925260ff16608085015260a084015260c083015260e08201526101000190565b604051602081830303815290604052805190602001206040516020016136e99291907f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b60408051601f198184030181529190528051602090910120613712610100850160e08601615904565b6040805160008152602081018083529390935260ff909116908201526101008401356060820152610120840135608082015260a0016020604051602081039080840390855afa158015613769573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158061379a57506033546001600160a01b03828116911614155b156137d1576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60c082013560009081526097602052604090205460ff161561381f576040517f1fb09b8000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060c00135600090815260976020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b835160609015613b6b5783518551146138a2576040517fff633a3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614905060008161394957836001600160a01b03166307af09266040518163ffffffff1660e01b8152600401602060405180830381865afa158015613920573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061394491906157ef565b6139ab565b836001600160a01b031663473f5adb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139ab91906157ef565b9050865167ffffffffffffffff8111156139c7576139c7614c46565b604051908082528060200260200182016040528015613a0d57816020015b6040805180820190915260008152606060208201528152602001906001900390816139e55790505b50925060005b8751811015613b6757600080613a5d888b8581518110613a3557613a3561562e565b60200260200101518b8681518110613a4f57613a4f61562e565b602002602001015188612f7e565b6040517fd8e8dbc70000000000000000000000000000000000000000000000000000000081526001600160a01b03808416600483015292945090925060009186169063d8e8dbc790602401602060405180830381865afa158015613ac5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ae9919061585d565b6040805180820182526000815281513060208281019190915269ffffffffffffffffffff87169382019390935260ff841660608201529293509190820190608001604051602081830303815290604052815250878581518110613b4e57613b4e61562e565b6020026020010181905250836001019350505050613a13565b5050505b949350505050565b6060808451865114613bb1576040517fff633a3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808515613bd4576009915084613bca57600b613bcd565b60095b9050613bea565b6008915084613be457600a613be7565b60085b90505b60005b8851811015613d46576000888281518110613c0a57613c0a61562e565b6020026020010151905080600003613c225750613d3e565b6000811215613cb757613cb060405180604001604052808560ff1681526020018c8581518110613c5457613c5461562e565b60200260200101518e85600003604051602001613c97939291909283526001600160a01b0391909116602083015267ffffffffffffffff16604082015260600190565b60408051601f1981840301815291905290528790613f38565b9550613d3c565b613d3960405180604001604052808660ff1681526020018c8581518110613ce057613ce061562e565b60200260200101518f85604051602001613d20939291909283526001600160a01b0391909116602083015267ffffffffffffffff16604082015260600190565b60408051601f1981840301815291905290528690613f38565b94505b505b600101613bed565b505050965096945050505050565b606081518351613d6491906159c1565b67ffffffffffffffff811115613d7c57613d7c614c46565b604051908082528060200260200182016040528015613dc257816020015b604080518082019091526000815260606020820152815260200190600190039081613d9a5790505b5090506000805b8451811015613e1557848181518110613de457613de461562e565b6020026020010151838381518110613dfe57613dfe61562e565b602090810291909101015260019182019101613dc9565b5060005b8351811015613e6557838181518110613e3457613e3461562e565b6020026020010151838381518110613e4e57613e4e61562e565b602090810291909101015260019182019101613e19565b505092915050565b6040805180820190915260008152606060208201526000831215613ebb57339450613eb87fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff846159d4565b92505b604051806040016040528083613ed2576009613ed5565b600a5b60ff168152602001848787604051602001613f1d9392919069ffffffffffffffffffff9390931683526001600160a01b0391909116602083015260ff16604082015260600190565b60408051601f19818403018152919052905295945050505050565b606082516001613f4891906159c1565b67ffffffffffffffff811115613f6057613f60614c46565b604051908082528060200260200182016040528015613fa657816020015b604080518082019091526000815260606020820152815260200190600190039081613f7e5790505b50905060005b8351811015613ff457838181518110613fc757613fc761562e565b6020026020010151828281518110613fe157613fe161562e565b6020908102919091010152600101613fac565b828282815181106140075761400761562e565b60200260200101819052505092915050565b60608251600161402991906159c1565b67ffffffffffffffff81111561404157614041614c46565b60405190808252806020026020018201604052801561408757816020015b60408051808201909152600081526060602082015281526020019060019003908161405f5790505b50905060005b8351811015613ff4578381815181106140a8576140a861562e565b60200260200101518282815181106140c2576140c261562e565b602090810291909101015260010161408d565b600061412a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166147f99092919063ffffffff16565b905080516000148061414b57508080602001905181019061414b919061565d565b6128fb5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610871565b60608060008467ffffffffffffffff8111156141db576141db614c46565b604051908082528060200260200182016040528015614204578160200160208202803683370190505b50905060008567ffffffffffffffff81111561422257614222614c46565b60405190808252806020026020018201604052801561424b578160200160208202803683370190505b50905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b031614905060005b8781101561473b576142be8989838181106142a7576142a761562e565b90506020028101906142b99190615a20565b61353a565b6000336001600160a01b038916036143d75760008a8a848181106142e4576142e461562e565b90506020028101906142f69190615a20565b614304906020810190614ba7565b6001600160a01b03163b11905080156143d7578989838181106143295761432961562e565b905060200281019061433b9190615a20565b614349906020810190614ba7565b6001600160a01b031663a06eb6578b8b858181106143695761436961562e565b905060200281019061437b9190615a20565b614389906040810190615574565b6040518363ffffffff1660e01b81526004016143a69291906155dc565b60006040518083038186803b1580156143be57600080fd5b505afa1580156143d2573d6000803e3d6000fd5b505050505b6000806144ef8c8c868181106143ef576143ef61562e565b90506020028101906144019190615a20565b61440f906020810190614ba7565b8b8e8e888181106144225761442261562e565b90506020028101906144349190615a20565b614442906040810190615574565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508f8f898181106144945761449461562e565b90506020028101906144a69190615a20565b6144b4906020810190615574565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c92508a9150613b739050565b8051919350915015614508576145058882613d54565b97505b8b8b8581811061451a5761451a61562e565b905060200281019061452c9190615a20565b60800135156146215760006145cf8d8d8781811061454c5761454c61562e565b905060200281019061455e9190615a20565b61456c906020810190614ba7565b8e8e8881811061457e5761457e61562e565b90506020028101906145909190615a20565b6145a1906080810190606001615904565b8f8f898181106145b3576145b361562e565b90506020028101906145c59190615a20565b6080013589613e6d565b905060008d8d878181106145e5576145e561562e565b90506020028101906145f79190615a20565b6080013513156146125761460b8982613f38565b985061461f565b61461c8382613f38565b92505b505b8151156146835761468060405180604001604052808e8e888181106146485761464861562e565b905060200281019061465a9190615a20565b614668906020810190614ba7565b6001600160a01b031681526020018490528a90614019565b98505b8b8b858181106146955761469561562e565b90506020028101906146a79190615a20565b60c001358785815181106146bd576146bd61562e565b6020026020010181815250508b8b858181106146db576146db61562e565b90506020028101906146ed9190615a20565b6146fb906020810190614ba7565b86858151811061470d5761470d61562e565b60200260200101906001600160a01b031690816001600160a01b03168152505083600101935050505061428a565b50856001600160a01b03167f28961876ada88ced44a4c08d307a65b9163f715a543387716865c82e35eb5fea8484604051614777929190615a5e565b60405180910390a250505094509492505050565b6147948161343f565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606147f08383604051806060016040528060278152602001615b0860279139614808565b90505b92915050565b6060613b6b8484600085614880565b6060600080856001600160a01b0316856040516148259190615ae2565b600060405180830381855af49150503d8060008114614860576040519150601f19603f3d011682016040523d82523d6000602084013e614865565b606091505b509150915061487686838387614972565b9695505050505050565b6060824710156148f85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610871565b600080866001600160a01b031685876040516149149190615ae2565b60006040518083038185875af1925050503d8060008114614951576040519150601f19603f3d011682016040523d82523d6000602084013e614956565b606091505b509150915061496787838387614972565b979650505050505050565b606083156149e15782516000036149da576001600160a01b0385163b6149da5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610871565b5081613b6b565b613b6b83838151156149f65781518083602001fd5b8060405162461bcd60e51b81526004016108719190615af4565b600060208284031215614a2257600080fd5b5035919050565b6001600160a01b038116811461097657600080fd5b60ff8116811461097657600080fd5b60008060008060008060c08789031215614a6657600080fd5b8635614a7181614a29565b95506020870135614a8181614a3e565b9450604087013593506060870135614a9881614a3e565b9598949750929560808101359460a0909101359350915050565b60008060408385031215614ac557600080fd5b8235614ad081614a29565b91506020830135614ae081614a29565b809150509250929050565b60008083601f840112614afd57600080fd5b50813567ffffffffffffffff811115614b1557600080fd5b602083019150836020828501011115614b2d57600080fd5b9250929050565b600080600080600060808688031215614b4c57600080fd5b8535614b5781614a29565b94506020860135614b6781614a3e565b935060408601359250606086013567ffffffffffffffff811115614b8a57600080fd5b614b9688828901614aeb565b969995985093965092949392505050565b600060208284031215614bb957600080fd5b8135614bc481614a29565b9392505050565b600080600080600080600060e0888a031215614be657600080fd5b8735614bf181614a29565b96506020880135614c0181614a3e565b9550604088013594506060880135614c1881614a3e565b93506080880135925060a0880135915060c0880135614c3681614a29565b8091505092959891949750929550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715614c9857614c98614c46565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715614cc757614cc7614c46565b604052919050565b600082601f830112614ce057600080fd5b813567ffffffffffffffff811115614cfa57614cfa614c46565b614d0d6020601f19601f84011601614c9e565b818152846020838601011115614d2257600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215614d5257600080fd5b8235614d5d81614a29565b9150602083013567ffffffffffffffff811115614d7957600080fd5b614d8585828601614ccf565b9150509250929050565b8035614d9a81614a29565b919050565b60006101408284031215614db257600080fd5b50919050565b60008083601f840112614dca57600080fd5b50813567ffffffffffffffff811115614de257600080fd5b6020830191508360208260051b8501011115614b2d57600080fd5b60008060008060008060808789031215614e1657600080fd5b8635614e2181614a29565b9550602087013567ffffffffffffffff80821115614e3e57600080fd5b614e4a8a838b01614d9f565b96506040890135915080821115614e6057600080fd5b614e6c8a838b01614db8565b90965094506060890135915080821115614e8557600080fd5b50614e9289828a01614db8565b979a9699509497509295939492505050565b600067ffffffffffffffff821115614ebe57614ebe614c46565b5060051b60200190565b600082601f830112614ed957600080fd5b614eeb614ee68335614ea4565b614c9e565b82358082526020808301929160051b850101851015614f0957600080fd5b602084015b6020853560051b86010181101561509d5767ffffffffffffffff8082351115614f3657600080fd5b813586016040601f19828a03011215614f4e57600080fd5b614f56614c75565b614f636020830135614a29565b602082013581528260408301351115614f7b57600080fd5b60408201358201915088603f830112614f9357600080fd5b614fa3614ee66020840135614ea4565b602083810135808352908201919060051b84016040018b1015614fc557600080fd5b604084015b6040602086013560051b86010181101561507d578581351115614fec57600080fd5b8035850160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0828f0301121561502257600080fd5b61502a614c75565b6150376040830135614a3e565b60408201358152876060830135111561504f57600080fd5b6150628e60406060850135850101614ccf565b60208201528085525050602083019250602081019050614fca565b508060208401525050808652505050602083019250602081019050614f0e565b50949350505050565b60008060008060008060008060008060c08b8d0312156150c557600080fd5b6150ce8b614d8f565b995060208b013567ffffffffffffffff808211156150eb57600080fd5b6150f78e838f01614db8565b909b50995060408d013591508082111561511057600080fd5b61511c8e838f01614db8565b909950975060608d013591508082111561513557600080fd5b6151418e838f01614db8565b909750955060808d013591508082111561515a57600080fd5b6151668e838f01614db8565b909550935060a08d013591508082111561517f57600080fd5b5061518c8d828e01614ec8565b9150509295989b9194979a5092959850565b600080600080608085870312156151b457600080fd5b843593506020850135925060408501356151cd81614a3e565b9396929550929360600135925050565b600080600080608085870312156151f357600080fd5b84356151fe81614a29565b9350602085013561520e81614a29565b925060408501356151cd81614a3e565b600080600080600060a0868803121561523657600080fd5b853561524181614a29565b9450602086013561525181614a29565b9350604086013561526181614a3e565b9250606086013561527181614a29565b949793965091946080013592915050565b60008060006040848603121561529757600080fd5b83356152a281614a29565b9250602084013567ffffffffffffffff8111156152be57600080fd5b6152ca86828701614db8565b9497909650939450505050565b60008060008060008060a087890312156152f057600080fd5b86356152fb81614a29565b9550602087013561530b81614a3e565b945060408701359350606087013567ffffffffffffffff81111561532e57600080fd5b61533a89828a01614aeb565b909450925050608087013561534e81614a29565b809150509295509295509295565b600080600080600080600060a0888a03121561537757600080fd5b873561538281614a29565b9650602088013567ffffffffffffffff8082111561539f57600080fd5b6153ab8b838c01614d9f565b975060408a01359150808211156153c157600080fd5b6153cd8b838c01614db8565b909750955060608a01359150808211156153e657600080fd5b506153f38a828b01614db8565b9094509250506080880135614c3681614a29565b60008060008060008060008060a0898b03121561542357600080fd5b883561542e81614a29565b9750602089013567ffffffffffffffff8082111561544b57600080fd5b6154578c838d01614db8565b909950975060408b013591508082111561547057600080fd5b61547c8c838d01614db8565b909750955060608b013591508082111561549557600080fd5b506154a28b828c01614db8565b90945092505060808901356154b681614a29565b809150509295985092959890939650565b60008060008060008060006080888a0312156154e257600080fd5b87356154ed81614a29565b9650602088013567ffffffffffffffff8082111561550a57600080fd5b6155168b838c01614db8565b909850965060408a013591508082111561552f57600080fd5b61553b8b838c01614db8565b909650945060608a013591508082111561555457600080fd5b506155618a828b01614db8565b989b979a50959850939692959293505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126155a957600080fd5b83018035915067ffffffffffffffff8211156155c457600080fd5b6020019150600581901b3603821315614b2d57600080fd5b6020815281602082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561561557600080fd5b8260051b80856040850137919091016040019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561566f57600080fd5b81518015158114614bc457600080fd5b60006020828403121561569157600080fd5b5051919050565b60005b838110156156b357818101518382015260200161569b565b50506000910152565b600081518084526156d4816020860160208601615698565b601f01601f19169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b858110156157475782840389528151805160ff1685528501516040868601819052615733818701836156bc565b9a87019a9550505090840190600101615706565b5091979650505050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b838110156157e1578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0018552815180516001600160a01b031684528701518784018790526157ce878501826156e8565b958801959350509086019060010161577b565b509098975050505050505050565b60006020828403121561580157600080fd5b8151614bc481614a29565b6000806040838503121561581f57600080fd5b825161582a81614a29565b6020840151909250614ae081614a3e565b6001600160a01b0383168152604060208201526000613b6b60408301846156e8565b60006020828403121561586f57600080fd5b8151614bc481614a3e565b83815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b6001600160a01b038316815260408101601683106158f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8260208301529392505050565b60006020828403121561591657600080fd5b8135614bc481614a3e565b60008184825b85811015615945578135835260209283019290910190600101615927565b509095945050505050565b60007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561597f57600080fd5b8260051b80858437919091019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156147f3576147f3615992565b808202600082127f800000000000000000000000000000000000000000000000000000000000000084141615615a0c57615a0c615992565b81810583148215176147f3576147f3615992565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112615a5457600080fd5b9190910192915050565b604080825283519082018190526000906020906060840190828701845b82811015615a9757815184529284019290840190600101615a7b565b5050508381038285015284518082528583019183019060005b81811015615ad55783516001600160a01b031683529284019291840191600101615ab0565b5090979650505050505050565b60008251615a54818460208701615698565b6020815260006147f060208301846156bc56fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220133a169bcefb757e4c9418673d2f54e4e9c68099ae15a8573ac20f348ce3e30b64736f6c634300081100330000000000000000000000009c742aef14cc875c49f52bbd4473b35bebad26ae000000000000000000000000341c281d11677795f1192bf1f7438666909841c8000000000000000000000000470f3b37b9b20e13b0a2a5965df6bd3f9640dfb4
Deployed Bytecode
0x6080604052600436106101b75760003560e01c80638da5cb5b116100ec578063c4d66de81161008a578063ee74885011610064578063ee7488501461052b578063eeed714814610561578063f2fde38b14610581578063fe01903d146105a157600080fd5b8063c4d66de8146104b7578063d108d194146104d7578063d1e96fc81461050b57600080fd5b8063b0fdab85116100c6578063b0fdab851461040d578063b54aa8be1461042d578063bccab1c614610463578063bf7e214f1461048357600080fd5b80638da5cb5b146103af578063a6f6f540146103cd578063a82b566c146103ed57600080fd5b80634281c53e116101595780637042853d116101335780637042853d1461033a578063715018a61461035a578063808553b91461036f57806385b522ed1461038f57600080fd5b80634281c53e146102f25780634f1ef2861461031257806352d1902d1461032557600080fd5b806331f111eb1161019557806331f111eb146102435780633644e515146102635780633659cfe6146102865780633759cace146102a657600080fd5b80630f6f1c83146101bc5780631414d6d61461020157806320aff42814610223575b600080fd5b3480156101c857600080fd5b506101ec6101d7366004614a10565b60976020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b34801561020d57600080fd5b5061022161021c366004614a4d565b6105c1565b005b34801561022f57600080fd5b5061022161023e366004614ab2565b6105ea565b34801561024f57600080fd5b5061022161025e366004614b34565b6106c7565b34801561026f57600080fd5b506102786106dc565b6040519081526020016101f8565b34801561029257600080fd5b506102216102a1366004614ba7565b6107d7565b3480156102b257600080fd5b506102da7f000000000000000000000000341c281d11677795f1192bf1f7438666909841c881565b6040516001600160a01b0390911681526020016101f8565b3480156102fe57600080fd5b5061022161030d366004614bcb565b610979565b610221610320366004614d3f565b6109ab565b34801561033157600080fd5b50610278610b39565b34801561034657600080fd5b50610221610355366004614dfd565b610bfe565b34801561036657600080fd5b50610221610cba565b34801561037b57600080fd5b5061022161038a3660046150a6565b610cce565b34801561039b57600080fd5b506102216103aa36600461519e565b61119e565b3480156103bb57600080fd5b506033546001600160a01b03166102da565b3480156103d957600080fd5b506102216103e83660046151dd565b611466565b3480156103f957600080fd5b5061027861040836600461521e565b6118f7565b34801561041957600080fd5b50610221610428366004615282565b611db6565b34801561043957600080fd5b506102da610448366004614ba7565b6099602052600090815260409020546001600160a01b031681565b34801561046f57600080fd5b5061022161047e3660046152d7565b611e7c565b34801561048f57600080fd5b506102da7f000000000000000000000000470f3b37b9b20e13b0a2a5965df6bd3f9640dfb481565b3480156104c357600080fd5b506102216104d2366004614ba7565b611e92565b3480156104e357600080fd5b506102da7f0000000000000000000000009c742aef14cc875c49f52bbd4473b35bebad26ae81565b34801561051757600080fd5b5061022161052636600461535c565b612053565b34801561053757600080fd5b506102da610546366004614ba7565b6098602052600090815260409020546001600160a01b031681565b34801561056d57600080fd5b5061022161057c366004615407565b612074565b34801561058d57600080fd5b5061022161059c366004614ba7565b6120a8565b3480156105ad57600080fd5b506102216105bc3660046154c7565b612135565b6105c961215c565b6105d8868686868686336121b5565b6105e26001606555565b505050505050565b6105f2612576565b6001600160a01b038216610632576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03828116600081815260986020908152604080832080549587167fffffffffffffffffffffffff00000000000000000000000000000000000000009687168117909155808452609983529281902080549095168417909455925190815290917fcd343f99315948a9186a773eab6d9017571a9be1337a150a1517555d16e28b6b910160405180910390a25050565b6106d58585858585336125ba565b5050505050565b60007f000000000000000000000000000000000000000000000000000000000000000146146107b2576107ad604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527fc66e37d5f583a79f144e1590643945b3f19d4d1f4c4324cd9bcac64fd93e5f09918101919091527f2a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de60608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b905090565b507f1b4e8bf92f2808bff2e377c2173eb3cffc1417b3ba63560cd7dcf6d4da58900390565b6001600160a01b037f000000000000000000000000e7587e41e356648a25e11d61e1b1c42853dab66316300361087a5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f000000000000000000000000e7587e41e356648a25e11d61e1b1c42853dab6636001600160a01b03166108d57f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b0316146109515760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610871565b61095a816128c0565b60408051600080825260208201909252610976918391906128c8565b50565b61098161215c565b610989612a6d565b610998878787878787876121b5565b6109a26001606555565b50505050505050565b6001600160a01b037f000000000000000000000000e7587e41e356648a25e11d61e1b1c42853dab663163003610a495760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401610871565b7f000000000000000000000000e7587e41e356648a25e11d61e1b1c42853dab6636001600160a01b0316610aa47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614610b205760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610871565b610b29826128c0565b610b35828260016128c8565b5050565b6000306001600160a01b037f000000000000000000000000e7587e41e356648a25e11d61e1b1c42853dab6631614610bd95760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610871565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b610c0661215c565b600080610c166020880188614ba7565b6001600160a01b03163b1190508015610c9f57610c366020870187614ba7565b6001600160a01b031663a06eb657610c516040890189615574565b6040518363ffffffff1660e01b8152600401610c6e9291906155dc565b60006040518083038186803b158015610c8657600080fd5b505afa158015610c9a573d6000803e3d6000fd5b505050505b610caf8787878787873388612b4c565b506105e26001606555565b610cc2612576565b610ccc6000612e8c565b565b610cd6612a6d565b60005b8681101561111a57308a8a83818110610cf457610cf461562e565b9050602002016020810190610d099190614ba7565b6001600160a01b031614610d9357610d938a8a83818110610d2c57610d2c61562e565b9050602002016020810190610d419190614ba7565b30888885818110610d5457610d5461562e565b905060200201358b8b86818110610d6d57610d6d61562e565b9050602002016020810190610d829190614ba7565b6001600160a01b0316929190612ef6565b6000848483818110610da757610da761562e565b9050602002016020810190610dbc9190614ba7565b6001600160a01b031603610ea857878782818110610ddc57610ddc61562e565b9050602002016020810190610df19190614ba7565b6001600160a01b031663095ea7b38c888885818110610e1257610e1261562e565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b1681526001600160a01b03909416600485015260200291909101356024830152506044016020604051808303816000875af1158015610e7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea2919061565d565b50611112565b878782818110610eba57610eba61562e565b9050602002016020810190610ecf9190614ba7565b6001600160a01b031663095ea7b3858584818110610eef57610eef61562e565b9050602002016020810190610f049190614ba7565b888885818110610f1657610f1661562e565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b1681526001600160a01b03909416600485015260200291909101356024830152506044016020604051808303816000875af1158015610f82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa6919061565d565b506000848483818110610fbb57610fbb61562e565b9050602002016020810190610fd09190614ba7565b6001600160a01b031663b6b55f25888885818110610ff057610ff061562e565b905060200201356040518263ffffffff1660e01b815260040161101591815260200190565b6020604051808303816000875af1158015611034573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611058919061567f565b905084848381811061106c5761106c61562e565b90506020020160208101906110819190614ba7565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038e8116600483015260248201849052919091169063095ea7b3906044016020604051808303816000875af11580156110eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110f919061565d565b50505b600101610cd9565b506040517fc46c67fb0000000000000000000000000000000000000000000000000000000081526001600160a01b038b169063c46c67fb90611160908490600401615754565b600060405180830381600087803b15801561117a57600080fd5b505af115801561118e573d6000803e3d6000fd5b5050505050505050505050505050565b6111a661215c565b60007f000000000000000000000000341c281d11677795f1192bf1f7438666909841c890506000816001600160a01b03166307af09266040518163ffffffff1660e01b8152600401602060405180830381865afa15801561120b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122f91906157ef565b6040517f1b3accac00000000000000000000000000000000000000000000000000000000815260ff861660048201526001600160a01b039190911690631b3accac906024016040805180830381865afa158015611290573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b4919061580c565b5090506112cc6001600160a01b038216333086612ef6565b60408051600280825260608201909252600091816020015b6040805180820190915260008152606060208201528152602001906001900390816112e4579050506040805180820182526000815281513060208281019190915292810188905260ff891660608201529293509190820190608001604051602081830303815290604052815250816000815181106113645761136461562e565b60200260200101819052506040518060400160405280600660ff16815260200188886040516020016113aa92919091825267ffffffffffffffff16602082015260400190565b604051602081830303815290604052815250816001815181106113cf576113cf61562e565b60209081029190910101526040517f8e1b5c0e0000000000000000000000000000000000000000000000000000000081526001600160a01b03841690638e1b5c0e90611421903390859060040161583b565b600060405180830381600087803b15801561143b57600080fd5b505af115801561144f573d6000803e3d6000fd5b505050505050506114606001606555565b50505050565b61146e61215c565b837f0000000000000000000000009c742aef14cc875c49f52bbd4473b35bebad26ae6001600160a01b039081169082161460008161150d57826001600160a01b03166307af09266040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114e4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150891906157ef565b61156f565b826001600160a01b031663473f5adb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561154b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156f91906157ef565b60408051600180825281830190925291925060009190816020015b60408051808201909152600081526060602082015281526020019060019003908161158a5790505060408051808201825260018152815169ffffffffffffffffffff8916602082810191909152309382019390935260ff8a1660608201529293509190820190608001604051602081830303815290604052815250816000815181106116185761161861562e565b60209081029190910101526040517f8e1b5c0e0000000000000000000000000000000000000000000000000000000081526001600160a01b03851690638e1b5c0e9061166a908a90859060040161583b565b600060405180830381600087803b15801561168457600080fd5b505af1158015611698573d6000803e3d6000fd5b50506040517f1b3accac00000000000000000000000000000000000000000000000000000000815260ff89166004820152600092506001600160a01b0385169150631b3accac906024016040805180830381865afa1580156116fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611722919061580c565b50905060008061173430848a89612f7e565b90925090506001600160a01b038216611779576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fd8e8dbc70000000000000000000000000000000000000000000000000000000081526001600160a01b03838116600483015286169063d8e8dbc790602401602060405180830381865afa1580156117d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117fc919061585d565b6040805180820182526000815281513060208281019190915269ffffffffffffffffffff86169382019390935260ff84166060820152929b509190820190608001604051602081830303815290604052815250846000815181106118625761186261562e565b60209081029190910101526040517f8e1b5c0e0000000000000000000000000000000000000000000000000000000081526001600160a01b03881690638e1b5c0e906118b4908d90889060040161583b565b600060405180830381600087803b1580156118ce57600080fd5b505af11580156118e2573d6000803e3d6000fd5b50505050505050505050506114606001606555565b600061190161215c565b611909612a6d565b60007f0000000000000000000000009c742aef14cc875c49f52bbd4473b35bebad26ae6001600160a01b0316876001600160a01b0316146119ab57866001600160a01b03166307af09266040518163ffffffff1660e01b8152600401602060405180830381865afa158015611982573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a691906157ef565b611a0d565b866001600160a01b031663473f5adb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119e9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a0d91906157ef565b6040517fd8e8dbc70000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152919091169063d8e8dbc790602401602060405180830381865afa158015611a6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a92919061585d565b90508060ff16600003611ad1576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001808252818301909252600091816020015b604080518082019091526000815260606020820152815260200190600190039081611ae85790505060408051808201825260018152815169ffffffffffffffffffff8816602082810191909152309382019390935260ff8a166060820152929350919082019060800160405160208183030381529060405281525081600081518110611b7657611b7661562e565b60209081029190910101526040517f8e1b5c0e0000000000000000000000000000000000000000000000000000000081526001600160a01b03891690638e1b5c0e90611bc8908a90859060040161583b565b600060405180830381600087803b158015611be257600080fd5b505af1158015611bf6573d6000803e3d6000fd5b50506040517fb6b55f25000000000000000000000000000000000000000000000000000000008152600481018790526001600160a01b038816925063b6b55f2591506024016020604051808303816000875af1158015611c5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c7e919061567f565b925082600003611cba576040517f749b593900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820182526000815281513060208281019190915269ffffffffffffffffffff87169382019390935260ff85166060820152909182019060800160405160208183030381529060405281525081600081518110611d1d57611d1d61562e565b60209081029190910101526040517f8e1b5c0e0000000000000000000000000000000000000000000000000000000081526001600160a01b03891690638e1b5c0e90611d6f908a90859060040161583b565b600060405180830381600087803b158015611d8957600080fd5b505af1158015611d9d573d6000803e3d6000fd5b505050505050611dad6001606555565b95945050505050565b611dbe612576565b8260005b828110156106d557816001600160a01b03166373d422af858584818110611deb57611deb61562e565b9050602002016020810190611e009190614ba7565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015611e5957600080fd5b505af1158015611e6d573d6000803e3d6000fd5b50505050806001019050611dc2565b611e84612a6d565b6105e28686868686866125ba565b600054610100900460ff1615808015611eb25750600054600160ff909116105b80611ecc5750303b158015611ecc575060005460ff166001145b611f3e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610871565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611f9c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6001600160a01b038216611fdc576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611fe582612e8c565b611fed613264565b8015610b3557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b61205b61215c565b612063612a6d565b610998878787878787876000612b4c565b61207c61215c565b612084612a6d565b61209488888888888888886132e1565b61209e6001606555565b5050505050505050565b6120b0612576565b6001600160a01b03811661212c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610871565b61097681612e8c565b61213d61215c565b61099887878787878787336132e1565b6001600160a01b03163b151590565b6002606554036121ae5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610871565b6002606555565b600087905060007f0000000000000000000000009c742aef14cc875c49f52bbd4473b35bebad26ae6001600160a01b0316896001600160a01b03161461225c57816001600160a01b03166307af09266040518163ffffffff1660e01b8152600401602060405180830381865afa158015612233573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225791906157ef565b6122be565b816001600160a01b031663473f5adb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561229a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122be91906157ef565b6040517f1b3accac00000000000000000000000000000000000000000000000000000000815260ff8a1660048201529091506000906001600160a01b03831690631b3accac906024016040805180830381865afa158015612323573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612347919061580c565b506001600160a01b0380821660009081526099602052604090205491925016308161236f5750845b604080516001808252818301909252600091816020015b6040805180820190915260008152606060208201528152602001906001900390816123865790505090506040518060400160405280600160ff1681526020018c848f6040516020016124059392919069ffffffffffffffffffff9390931683526001600160a01b0391909116602083015260ff16604082015260600190565b6040516020818303038152906040528152508160008151811061242a5761242a61562e565b60209081029190910101526040517f8e1b5c0e0000000000000000000000000000000000000000000000000000000081526001600160a01b03871690638e1b5c0e9061247c908a90859060040161583b565b600060405180830381600087803b15801561249657600080fd5b505af11580156124aa573d6000803e3d6000fd5b505050506001600160a01b03831615612560576040517fc2930c450000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152602482018d905260ff8c166044830152606482018b9052608482018a905285169063c2930c459060a4016020604051808303816000875af115801561253c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118e919061567f565b50505050505050505050505050565b6001606555565b6033546001600160a01b03163314610ccc576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001808252818301909252879160009190816020015b6040805180820190915260008152606060208201528152602001906001900390816125d45790505060408051808201825260018152815169ffffffffffffffffffff8a16602082810191909152309382019390935260ff8b1660608201529293509190820190608001604051602081830303815290604052815250816000815181106126625761266261562e565b60209081029190910101526040517f8e1b5c0e0000000000000000000000000000000000000000000000000000000081526001600160a01b03831690638e1b5c0e906126b4908690859060040161583b565b600060405180830381600087803b1580156126ce57600080fd5b505af11580156126e2573d6000803e3d6000fd5b5050505060007f0000000000000000000000009c742aef14cc875c49f52bbd4473b35bebad26ae6001600160a01b0316896001600160a01b03161461278857826001600160a01b03166307af09266040518163ffffffff1660e01b8152600401602060405180830381865afa15801561275f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278391906157ef565b6127ea565b826001600160a01b031663473f5adb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ea91906157ef565b6040517f1b3accac00000000000000000000000000000000000000000000000000000000815260ff8a1660048201529091506000906001600160a01b03831690631b3accac906024016040805180830381865afa15801561284f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612873919061580c565b506040517f7641e6f30000000000000000000000000000000000000000000000000000000081529091506001600160a01b03821690637641e6f390611160908b908b908b9060040161587a565b610976612576565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612900576128fb8361343f565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561295a575060408051601f3d908101601f191682019092526129579181019061567f565b60015b6129cc5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152608401610871565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612a615760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608401610871565b506128fb838383613515565b6040517fea7ca2760000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000470f3b37b9b20e13b0a2a5965df6bd3f9640dfb4169063ea7ca27690612ad5903390600d906004016158b0565b602060405180830381865afa158015612af2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b16919061565d565b610ccc576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b558761353a565b60007f0000000000000000000000009c742aef14cc875c49f52bbd4473b35bebad26ae6001600160a01b0316896001600160a01b03161490506000612c0188888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808c0282810182019093528b82529093508b92508a9182918501908490808284376000920191909152508992508f915061385d9050565b9050600080612caf612c1660208d018d614ba7565b87612c2460408f018f615574565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508e8060200190612c749190615574565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508b92508c9150613b739050565b9092509050612cbe8382613d54565b925060808b013515612d29576000612cfa612cdc60208e018e614ba7565b8d6060016020810190612cef9190615904565b8e6080013588613e6d565b905060008c608001351315612d1a57612d138482613f38565b9350612d27565b612d248382613f38565b92505b505b815160609015612d6f57612d6c60405180604001604052808e6000016020810190612d549190614ba7565b6001600160a01b031681526020018590528290614019565b90505b835115612da957612da66040518060400160405280896001600160a01b03168152602001868152508261401990919063ffffffff16565b90505b6001600160a01b038716612dc060208e018e614ba7565b6001600160a01b03167f977d0b17c986a7a0c40ce64bd03ac2f5e30e4a059d775ae65b34e51c38eb41538e60c00135604051612dfe91815260200190565b60405180910390a36040517fc46c67fb0000000000000000000000000000000000000000000000000000000081526001600160a01b038e169063c46c67fb90612e4b908490600401615754565b600060405180830381600087803b158015612e6557600080fd5b505af1158015612e79573d6000803e3d6000fd5b5050505050505050505050505050505050565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526114609085906140d5565b600080848184612fae577f000000000000000000000000341c281d11677795f1192bf1f7438666909841c8612fd0565b7f0000000000000000000000009c742aef14cc875c49f52bbd4473b35bebad26ae5b90506001600160a01b0388163014612ff757612ff76001600160a01b038316893089612ef6565b6001600160a01b03808816600090815260986020526040902054169350836130b3576040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526024820188905283169063095ea7b3906044016020604051808303816000875af1158015613081573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a5919061565d565b50868693509350505061325b565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526024820188905283169063095ea7b3906044016020604051808303816000875af115801561311b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061313f919061565d565b506040517fb6b55f250000000000000000000000000000000000000000000000000000000081526004810187905284906001600160a01b0382169063b6b55f25906024016020604051808303816000875af11580156131a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131c6919061567f565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152602482018390529195509082169063095ea7b3906044016020604051808303816000875af1158015613232573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613256919061565d565b505050505b94509492505050565b600054610100900460ff1661256f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610871565b600061335486868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808a028281018201909352898252909350899250889182918501908490808284376000920191909152508792508e915061385d9050565b90506000806133658b8b8b876141bd565b9150915060008351118061337a575060008151115b156133bb576133b86040518060400160405280866001600160a01b031681526020016133af8487613d5490919063ffffffff16565b90528390614019565b91505b6040517fc46c67fb0000000000000000000000000000000000000000000000000000000081526001600160a01b038c169063c46c67fb90613400908590600401615754565b600060405180830381600087803b15801561341a57600080fd5b505af115801561342e573d6000803e3d6000fd5b505050505050505050505050505050565b6001600160a01b0381163b6134bc5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610871565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b61351e8361478b565b60008251118061352b5750805b156128fb5761146083836147cb565b428160a0013511613577576040517ff4732ca300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060016135836106dc565b7f32f9555cd4fc061398f70871cdfce12ed4137df14855f94c66900f5f71214eba6135b16020860186614ba7565b6135be6020870187615574565b6040516020016135cf929190615921565b604051602081830303815290604052805190602001208680604001906135f59190615574565b604051602001613606929190615950565b60408051601f19818403018152919052805160209091012061362e6080890160608a01615904565b88608001358960a001358a60c001356040516020016136919897969594939291909788526001600160a01b039690961660208801526040870194909452606086019290925260ff16608085015260a084015260c083015260e08201526101000190565b604051602081830303815290604052805190602001206040516020016136e99291907f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b60408051601f198184030181529190528051602090910120613712610100850160e08601615904565b6040805160008152602081018083529390935260ff909116908201526101008401356060820152610120840135608082015260a0016020604051602081039080840390855afa158015613769573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158061379a57506033546001600160a01b03828116911614155b156137d1576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60c082013560009081526097602052604090205460ff161561381f576040517f1fb09b8000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060c00135600090815260976020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b835160609015613b6b5783518551146138a2576040517fff633a3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f0000000000000000000000009c742aef14cc875c49f52bbd4473b35bebad26ae6001600160a01b0316836001600160a01b031614905060008161394957836001600160a01b03166307af09266040518163ffffffff1660e01b8152600401602060405180830381865afa158015613920573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061394491906157ef565b6139ab565b836001600160a01b031663473f5adb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139ab91906157ef565b9050865167ffffffffffffffff8111156139c7576139c7614c46565b604051908082528060200260200182016040528015613a0d57816020015b6040805180820190915260008152606060208201528152602001906001900390816139e55790505b50925060005b8751811015613b6757600080613a5d888b8581518110613a3557613a3561562e565b60200260200101518b8681518110613a4f57613a4f61562e565b602002602001015188612f7e565b6040517fd8e8dbc70000000000000000000000000000000000000000000000000000000081526001600160a01b03808416600483015292945090925060009186169063d8e8dbc790602401602060405180830381865afa158015613ac5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ae9919061585d565b6040805180820182526000815281513060208281019190915269ffffffffffffffffffff87169382019390935260ff841660608201529293509190820190608001604051602081830303815290604052815250878581518110613b4e57613b4e61562e565b6020026020010181905250836001019350505050613a13565b5050505b949350505050565b6060808451865114613bb1576040517fff633a3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808515613bd4576009915084613bca57600b613bcd565b60095b9050613bea565b6008915084613be457600a613be7565b60085b90505b60005b8851811015613d46576000888281518110613c0a57613c0a61562e565b6020026020010151905080600003613c225750613d3e565b6000811215613cb757613cb060405180604001604052808560ff1681526020018c8581518110613c5457613c5461562e565b60200260200101518e85600003604051602001613c97939291909283526001600160a01b0391909116602083015267ffffffffffffffff16604082015260600190565b60408051601f1981840301815291905290528790613f38565b9550613d3c565b613d3960405180604001604052808660ff1681526020018c8581518110613ce057613ce061562e565b60200260200101518f85604051602001613d20939291909283526001600160a01b0391909116602083015267ffffffffffffffff16604082015260600190565b60408051601f1981840301815291905290528690613f38565b94505b505b600101613bed565b505050965096945050505050565b606081518351613d6491906159c1565b67ffffffffffffffff811115613d7c57613d7c614c46565b604051908082528060200260200182016040528015613dc257816020015b604080518082019091526000815260606020820152815260200190600190039081613d9a5790505b5090506000805b8451811015613e1557848181518110613de457613de461562e565b6020026020010151838381518110613dfe57613dfe61562e565b602090810291909101015260019182019101613dc9565b5060005b8351811015613e6557838181518110613e3457613e3461562e565b6020026020010151838381518110613e4e57613e4e61562e565b602090810291909101015260019182019101613e19565b505092915050565b6040805180820190915260008152606060208201526000831215613ebb57339450613eb87fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff846159d4565b92505b604051806040016040528083613ed2576009613ed5565b600a5b60ff168152602001848787604051602001613f1d9392919069ffffffffffffffffffff9390931683526001600160a01b0391909116602083015260ff16604082015260600190565b60408051601f19818403018152919052905295945050505050565b606082516001613f4891906159c1565b67ffffffffffffffff811115613f6057613f60614c46565b604051908082528060200260200182016040528015613fa657816020015b604080518082019091526000815260606020820152815260200190600190039081613f7e5790505b50905060005b8351811015613ff457838181518110613fc757613fc761562e565b6020026020010151828281518110613fe157613fe161562e565b6020908102919091010152600101613fac565b828282815181106140075761400761562e565b60200260200101819052505092915050565b60608251600161402991906159c1565b67ffffffffffffffff81111561404157614041614c46565b60405190808252806020026020018201604052801561408757816020015b60408051808201909152600081526060602082015281526020019060019003908161405f5790505b50905060005b8351811015613ff4578381815181106140a8576140a861562e565b60200260200101518282815181106140c2576140c261562e565b602090810291909101015260010161408d565b600061412a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166147f99092919063ffffffff16565b905080516000148061414b57508080602001905181019061414b919061565d565b6128fb5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610871565b60608060008467ffffffffffffffff8111156141db576141db614c46565b604051908082528060200260200182016040528015614204578160200160208202803683370190505b50905060008567ffffffffffffffff81111561422257614222614c46565b60405190808252806020026020018201604052801561424b578160200160208202803683370190505b50905060007f0000000000000000000000009c742aef14cc875c49f52bbd4473b35bebad26ae6001600160a01b0316896001600160a01b031614905060005b8781101561473b576142be8989838181106142a7576142a761562e565b90506020028101906142b99190615a20565b61353a565b6000336001600160a01b038916036143d75760008a8a848181106142e4576142e461562e565b90506020028101906142f69190615a20565b614304906020810190614ba7565b6001600160a01b03163b11905080156143d7578989838181106143295761432961562e565b905060200281019061433b9190615a20565b614349906020810190614ba7565b6001600160a01b031663a06eb6578b8b858181106143695761436961562e565b905060200281019061437b9190615a20565b614389906040810190615574565b6040518363ffffffff1660e01b81526004016143a69291906155dc565b60006040518083038186803b1580156143be57600080fd5b505afa1580156143d2573d6000803e3d6000fd5b505050505b6000806144ef8c8c868181106143ef576143ef61562e565b90506020028101906144019190615a20565b61440f906020810190614ba7565b8b8e8e888181106144225761442261562e565b90506020028101906144349190615a20565b614442906040810190615574565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508f8f898181106144945761449461562e565b90506020028101906144a69190615a20565b6144b4906020810190615574565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c92508a9150613b739050565b8051919350915015614508576145058882613d54565b97505b8b8b8581811061451a5761451a61562e565b905060200281019061452c9190615a20565b60800135156146215760006145cf8d8d8781811061454c5761454c61562e565b905060200281019061455e9190615a20565b61456c906020810190614ba7565b8e8e8881811061457e5761457e61562e565b90506020028101906145909190615a20565b6145a1906080810190606001615904565b8f8f898181106145b3576145b361562e565b90506020028101906145c59190615a20565b6080013589613e6d565b905060008d8d878181106145e5576145e561562e565b90506020028101906145f79190615a20565b6080013513156146125761460b8982613f38565b985061461f565b61461c8382613f38565b92505b505b8151156146835761468060405180604001604052808e8e888181106146485761464861562e565b905060200281019061465a9190615a20565b614668906020810190614ba7565b6001600160a01b031681526020018490528a90614019565b98505b8b8b858181106146955761469561562e565b90506020028101906146a79190615a20565b60c001358785815181106146bd576146bd61562e565b6020026020010181815250508b8b858181106146db576146db61562e565b90506020028101906146ed9190615a20565b6146fb906020810190614ba7565b86858151811061470d5761470d61562e565b60200260200101906001600160a01b031690816001600160a01b03168152505083600101935050505061428a565b50856001600160a01b03167f28961876ada88ced44a4c08d307a65b9163f715a543387716865c82e35eb5fea8484604051614777929190615a5e565b60405180910390a250505094509492505050565b6147948161343f565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606147f08383604051806060016040528060278152602001615b0860279139614808565b90505b92915050565b6060613b6b8484600085614880565b6060600080856001600160a01b0316856040516148259190615ae2565b600060405180830381855af49150503d8060008114614860576040519150601f19603f3d011682016040523d82523d6000602084013e614865565b606091505b509150915061487686838387614972565b9695505050505050565b6060824710156148f85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610871565b600080866001600160a01b031685876040516149149190615ae2565b60006040518083038185875af1925050503d8060008114614951576040519150601f19603f3d011682016040523d82523d6000602084013e614956565b606091505b509150915061496787838387614972565b979650505050505050565b606083156149e15782516000036149da576001600160a01b0385163b6149da5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610871565b5081613b6b565b613b6b83838151156149f65781518083602001fd5b8060405162461bcd60e51b81526004016108719190615af4565b600060208284031215614a2257600080fd5b5035919050565b6001600160a01b038116811461097657600080fd5b60ff8116811461097657600080fd5b60008060008060008060c08789031215614a6657600080fd5b8635614a7181614a29565b95506020870135614a8181614a3e565b9450604087013593506060870135614a9881614a3e565b9598949750929560808101359460a0909101359350915050565b60008060408385031215614ac557600080fd5b8235614ad081614a29565b91506020830135614ae081614a29565b809150509250929050565b60008083601f840112614afd57600080fd5b50813567ffffffffffffffff811115614b1557600080fd5b602083019150836020828501011115614b2d57600080fd5b9250929050565b600080600080600060808688031215614b4c57600080fd5b8535614b5781614a29565b94506020860135614b6781614a3e565b935060408601359250606086013567ffffffffffffffff811115614b8a57600080fd5b614b9688828901614aeb565b969995985093965092949392505050565b600060208284031215614bb957600080fd5b8135614bc481614a29565b9392505050565b600080600080600080600060e0888a031215614be657600080fd5b8735614bf181614a29565b96506020880135614c0181614a3e565b9550604088013594506060880135614c1881614a3e565b93506080880135925060a0880135915060c0880135614c3681614a29565b8091505092959891949750929550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715614c9857614c98614c46565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715614cc757614cc7614c46565b604052919050565b600082601f830112614ce057600080fd5b813567ffffffffffffffff811115614cfa57614cfa614c46565b614d0d6020601f19601f84011601614c9e565b818152846020838601011115614d2257600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215614d5257600080fd5b8235614d5d81614a29565b9150602083013567ffffffffffffffff811115614d7957600080fd5b614d8585828601614ccf565b9150509250929050565b8035614d9a81614a29565b919050565b60006101408284031215614db257600080fd5b50919050565b60008083601f840112614dca57600080fd5b50813567ffffffffffffffff811115614de257600080fd5b6020830191508360208260051b8501011115614b2d57600080fd5b60008060008060008060808789031215614e1657600080fd5b8635614e2181614a29565b9550602087013567ffffffffffffffff80821115614e3e57600080fd5b614e4a8a838b01614d9f565b96506040890135915080821115614e6057600080fd5b614e6c8a838b01614db8565b90965094506060890135915080821115614e8557600080fd5b50614e9289828a01614db8565b979a9699509497509295939492505050565b600067ffffffffffffffff821115614ebe57614ebe614c46565b5060051b60200190565b600082601f830112614ed957600080fd5b614eeb614ee68335614ea4565b614c9e565b82358082526020808301929160051b850101851015614f0957600080fd5b602084015b6020853560051b86010181101561509d5767ffffffffffffffff8082351115614f3657600080fd5b813586016040601f19828a03011215614f4e57600080fd5b614f56614c75565b614f636020830135614a29565b602082013581528260408301351115614f7b57600080fd5b60408201358201915088603f830112614f9357600080fd5b614fa3614ee66020840135614ea4565b602083810135808352908201919060051b84016040018b1015614fc557600080fd5b604084015b6040602086013560051b86010181101561507d578581351115614fec57600080fd5b8035850160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0828f0301121561502257600080fd5b61502a614c75565b6150376040830135614a3e565b60408201358152876060830135111561504f57600080fd5b6150628e60406060850135850101614ccf565b60208201528085525050602083019250602081019050614fca565b508060208401525050808652505050602083019250602081019050614f0e565b50949350505050565b60008060008060008060008060008060c08b8d0312156150c557600080fd5b6150ce8b614d8f565b995060208b013567ffffffffffffffff808211156150eb57600080fd5b6150f78e838f01614db8565b909b50995060408d013591508082111561511057600080fd5b61511c8e838f01614db8565b909950975060608d013591508082111561513557600080fd5b6151418e838f01614db8565b909750955060808d013591508082111561515a57600080fd5b6151668e838f01614db8565b909550935060a08d013591508082111561517f57600080fd5b5061518c8d828e01614ec8565b9150509295989b9194979a5092959850565b600080600080608085870312156151b457600080fd5b843593506020850135925060408501356151cd81614a3e565b9396929550929360600135925050565b600080600080608085870312156151f357600080fd5b84356151fe81614a29565b9350602085013561520e81614a29565b925060408501356151cd81614a3e565b600080600080600060a0868803121561523657600080fd5b853561524181614a29565b9450602086013561525181614a29565b9350604086013561526181614a3e565b9250606086013561527181614a29565b949793965091946080013592915050565b60008060006040848603121561529757600080fd5b83356152a281614a29565b9250602084013567ffffffffffffffff8111156152be57600080fd5b6152ca86828701614db8565b9497909650939450505050565b60008060008060008060a087890312156152f057600080fd5b86356152fb81614a29565b9550602087013561530b81614a3e565b945060408701359350606087013567ffffffffffffffff81111561532e57600080fd5b61533a89828a01614aeb565b909450925050608087013561534e81614a29565b809150509295509295509295565b600080600080600080600060a0888a03121561537757600080fd5b873561538281614a29565b9650602088013567ffffffffffffffff8082111561539f57600080fd5b6153ab8b838c01614d9f565b975060408a01359150808211156153c157600080fd5b6153cd8b838c01614db8565b909750955060608a01359150808211156153e657600080fd5b506153f38a828b01614db8565b9094509250506080880135614c3681614a29565b60008060008060008060008060a0898b03121561542357600080fd5b883561542e81614a29565b9750602089013567ffffffffffffffff8082111561544b57600080fd5b6154578c838d01614db8565b909950975060408b013591508082111561547057600080fd5b61547c8c838d01614db8565b909750955060608b013591508082111561549557600080fd5b506154a28b828c01614db8565b90945092505060808901356154b681614a29565b809150509295985092959890939650565b60008060008060008060006080888a0312156154e257600080fd5b87356154ed81614a29565b9650602088013567ffffffffffffffff8082111561550a57600080fd5b6155168b838c01614db8565b909850965060408a013591508082111561552f57600080fd5b61553b8b838c01614db8565b909650945060608a013591508082111561555457600080fd5b506155618a828b01614db8565b989b979a50959850939692959293505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126155a957600080fd5b83018035915067ffffffffffffffff8211156155c457600080fd5b6020019150600581901b3603821315614b2d57600080fd5b6020815281602082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561561557600080fd5b8260051b80856040850137919091016040019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561566f57600080fd5b81518015158114614bc457600080fd5b60006020828403121561569157600080fd5b5051919050565b60005b838110156156b357818101518382015260200161569b565b50506000910152565b600081518084526156d4816020860160208601615698565b601f01601f19169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b858110156157475782840389528151805160ff1685528501516040868601819052615733818701836156bc565b9a87019a9550505090840190600101615706565b5091979650505050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b838110156157e1578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0018552815180516001600160a01b031684528701518784018790526157ce878501826156e8565b958801959350509086019060010161577b565b509098975050505050505050565b60006020828403121561580157600080fd5b8151614bc481614a29565b6000806040838503121561581f57600080fd5b825161582a81614a29565b6020840151909250614ae081614a3e565b6001600160a01b0383168152604060208201526000613b6b60408301846156e8565b60006020828403121561586f57600080fd5b8151614bc481614a3e565b83815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b6001600160a01b038316815260408101601683106158f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8260208301529392505050565b60006020828403121561591657600080fd5b8135614bc481614a3e565b60008184825b85811015615945578135835260209283019290910190600101615927565b509095945050505050565b60007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561597f57600080fd5b8260051b80858437919091019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156147f3576147f3615992565b808202600082127f800000000000000000000000000000000000000000000000000000000000000084141615615a0c57615a0c615992565b81810583148215176147f3576147f3615992565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112615a5457600080fd5b9190910192915050565b604080825283519082018190526000906020906060840190828701845b82811015615a9757815184529284019290840190600101615a7b565b5050508381038285015284518082528583019183019060005b81811015615ad55783516001600160a01b031683529284019291840191600101615ab0565b5090979650505050505050565b60008251615a54818460208701615698565b6020815260006147f060208301846156bc56fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220133a169bcefb757e4c9418673d2f54e4e9c68099ae15a8573ac20f348ce3e30b64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009c742aef14cc875c49f52bbd4473b35bebad26ae000000000000000000000000341c281d11677795f1192bf1f7438666909841c8000000000000000000000000470f3b37b9b20e13b0a2a5965df6bd3f9640dfb4
-----Decoded View---------------
Arg [0] : _meCash (address): 0x9c742Aef14CC875C49f52bBD4473B35beBAD26Ae
Arg [1] : _mePhysical (address): 0x341C281d11677795F1192bF1f7438666909841c8
Arg [2] : _authority (address): 0x470f3b37B9B20E13b0A2a5965Df6bD3f9640DFB4
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000009c742aef14cc875c49f52bbd4473b35bebad26ae
Arg [1] : 000000000000000000000000341c281d11677795f1192bf1f7438666909841c8
Arg [2] : 000000000000000000000000470f3b37b9b20e13b0a2a5965df6bd3f9640dfb4
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.