Feature Tip: Add private address tag to any address under My Name Tag !
ERC-20
Overview
Max Total Supply
579.436555 ERC20 ***
Holders
5
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 6 Decimals)
Balance
10.249655 ERC20 ***Value
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0x3393f10c...7259A0A1B The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
ERC5095
Compiler Version
v0.8.16+commit.07a7930e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.16; /// @dev A single custom error capable of indicating a wide range of detected errors by providing /// an error code value whose string representation is documented in errors.txt, and any possible other values /// that are pertinent to the error. error Exception(uint8, uint256, uint256, address, address);
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.16; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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 `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Returns the number of decimals the token uses - e.g. 8, means to * divide the token amount by 100000000 to get its user representation. */ function decimals() external view returns (uint8); /** * @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 ); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.16; import 'src/interfaces/IERC20.sol'; interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.16; import 'src/interfaces/IERC20Metadata.sol'; /** * @dev Interface of the ERC2612 standard as defined in the EIP. * * Adds the {permit} method, which can be used to change one's * {IERC20-allowance} without having to send a transaction, by signing a * message. This allows users to spend tokens without having to hold Ether. * * See https://eips.ethereum.org/EIPS/eip-2612. */ interface IERC2612 is IERC20Metadata { /** * @dev Sets `amount` 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: * * - `owner` cannot be the zero address. * - `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 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current ERC2612 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); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.16; import 'src/interfaces/IERC2612.sol'; interface IERC5095 is IERC2612 { function maturity() external view returns (uint256); function underlying() external view returns (address); function convertToUnderlying(uint256) external view returns (uint256); function convertToShares(uint256) external view returns (uint256); function maxRedeem(address) external view returns (uint256); function previewRedeem(uint256) external view returns (uint256); function maxWithdraw(address) external view returns (uint256); function previewWithdraw(uint256) external view returns (uint256); function previewDeposit(uint256) external view returns (uint256); function withdraw( uint256, address, address ) external returns (uint256); function redeem( uint256, address, address ) external returns (uint256); function deposit(uint256, address) external returns (uint256); function mint(uint256, address) external returns (uint256); function authMint(address, uint256) external returns (bool); function authBurn(address, uint256) external returns (bool); function authApprove( address, address, uint256 ) external returns (bool); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.16; interface IMarketPlace { function markets( address, uint256, uint256 ) external returns (address); function pools(address, uint256) external view returns (address); function sellPrincipalToken( address, uint256, uint128, uint128 ) external returns (uint128); function buyPrincipalToken( address, uint256, uint128, uint128 ) external returns (uint128); function sellUnderlying( address, uint256, uint128, uint128 ) external returns (uint128); function buyUnderlying( address, uint256, uint128, uint128 ) external returns (uint128); function redeemer() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.16; interface IRedeemer { function authRedeem( address underlying, uint256 maturity, address from, address to, uint256 amount ) external returns (uint256); function approve(address p) external; function holdings(address u, uint256 m) external view returns (uint256); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.16; import 'src/interfaces/IERC20.sol'; interface IYield { function maturity() external view returns (uint32); function base() external view returns (IERC20); function sellBase(address, uint128) external returns (uint128); function sellBasePreview(uint128) external view returns (uint128); function fyToken() external returns (address); function sellFYToken(address, uint128) external returns (uint128); function sellFYTokenPreview(uint128) external view returns (uint128); function buyBase( address, uint128, uint128 ) external returns (uint128); function buyBasePreview(uint128) external view returns (uint128); function buyFYToken( address, uint128, uint128 ) external returns (uint128); function buyFYTokenPreview(uint128) external view returns (uint128); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; library Cast { /// @dev Safely cast an uint256 to an uint128 /// @param n the u256 to cast to u128 function u128(uint256 n) internal pure returns (uint128) { if (n > type(uint128).max) { revert(); } return uint128(n); } }
// SPDX-License-Identifier: UNLICENSED // Adapted from: https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol pragma solidity ^0.8.13; import 'src/interfaces/IERC20.sol'; /** @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. @author Modified from Gnosis (https://github.com/gnosis/gp-v2-contracts/blob/main/src/contracts/libraries/GPv2SafeERC20.sol) @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. */ library Safe { /// @param e Erc20 token to execute the call with /// @param t To address /// @param a Amount being transferred function transfer( IERC20 e, address t, uint256 a ) internal { bool result; assembly { // Get a pointer to some free memory. let pointer := mload(0x40) // Write the abi-encoded calldata to memory piece by piece: mstore( pointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000 ) // Begin with the function selector. mstore( add(pointer, 4), and(t, 0xffffffffffffffffffffffffffffffffffffffff) ) // Mask and append the "to" argument. mstore(add(pointer, 36), a) // Finally append the "amount" argument. No mask as it's a full 32 byte value. // Call the token and store if it succeeded or not. // We use 68 because the calldata length is 4 + 32 * 2. result := call(gas(), e, 0, pointer, 68, 0, 0) } require(success(result), 'transfer failed'); } /// @param e Erc20 token to execute the call with /// @param f From address /// @param t To address /// @param a Amount being transferred function transferFrom( IERC20 e, address f, address t, uint256 a ) internal { bool result; assembly { // Get a pointer to some free memory. let pointer := mload(0x40) // Write the abi-encoded calldata to memory piece by piece: mstore( pointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000 ) // Begin with the function selector. mstore( add(pointer, 4), and(f, 0xffffffffffffffffffffffffffffffffffffffff) ) // Mask and append the "from" argument. mstore( add(pointer, 36), and(t, 0xffffffffffffffffffffffffffffffffffffffff) ) // Mask and append the "to" argument. mstore(add(pointer, 68), a) // Finally append the "amount" argument. No mask as it's a full 32 byte value. // Call the token and store if it succeeded or not. // We use 100 because the calldata length is 4 + 32 * 3. result := call(gas(), e, 0, pointer, 100, 0, 0) } require(success(result), 'transfer from failed'); } /// @notice normalize the acceptable values of true or null vs the unacceptable value of false (or something malformed) /// @param r Return value from the assembly `call()` to Erc20['selector'] function success(bool r) private pure returns (bool) { bool result; assembly { // Get how many bytes the call returned. let returnDataSize := returndatasize() // If the call reverted: if iszero(r) { // Copy the revert message into memory. returndatacopy(0, 0, returnDataSize) // Revert with the same message. revert(0, returnDataSize) } switch returnDataSize case 32 { // Copy the return data into memory. returndatacopy(0, 0, returnDataSize) // Set success to whether it returned true. result := iszero(iszero(mload(0))) } case 0 { // There was no return data. result := 1 } default { // It returned some malformed input. result := 0 } } return result; } function approve( IERC20 token, address to, uint256 amount ) internal { bool callStatus; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata to memory piece by piece: mstore( freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000 ) // Begin with the function selector. mstore( add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff) ) // Mask and append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value. // Call the token and store if it succeeded or not. // We use 68 because the calldata length is 4 + 32 * 2. callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0) } require(didLastOptionalReturnCallSucceed(callStatus), 'APPROVE_FAILED'); } /*/////////////////////////////////////////////////////////////// INTERNAL HELPER LOGIC //////////////////////////////////////////////////////////////*/ function didLastOptionalReturnCallSucceed(bool callStatus) private pure returns (bool) { bool result; assembly { // Get how many bytes the call returned. let returnDataSize := returndatasize() // If the call reverted: if iszero(callStatus) { // Copy the revert message into memory. returndatacopy(0, 0, returnDataSize) // Revert with the same message. revert(0, returnDataSize) } switch returnDataSize case 32 { // Copy the return data into memory. returndatacopy(0, 0, returnDataSize) // Set success to whether it returned true. result := iszero(iszero(mload(0))) } case 0 { // There was no return data. result := 1 } default { // It returned some malformed input. result := 0 } } return result; } }
// SPDX-License-Identifier: MIT // Inspired on token.sol from DappHub. Natspec adpated from OpenZeppelin. pragma solidity 0.8.16; import 'src/interfaces/IERC20Metadata.sol'; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Calls to {transferFrom} do not check for allowance if the caller is the owner * of the funds. This allows to reduce the number of approvals that are necessary. * * Finally, {transferFrom} does not decrease the allowance if it is set to * type(uint256).max. This reduces the gas costs without any likely impact. */ contract ERC20 is IERC20Metadata { uint256 internal _totalSupply; mapping(address => uint256) internal _balanceOf; mapping(address => mapping(address => uint256)) internal _allowance; string public override name = '???'; string public override symbol = '???'; uint8 public override decimals = 18; /** * @dev Sets the values for {name}, {symbol} and {decimals}. */ constructor( string memory name_, string memory symbol_, uint8 decimals_ ) { name = name_; symbol = symbol_; decimals = decimals_; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() external view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address guy) external view virtual override returns (uint256) { return _balanceOf[guy]; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) external view virtual override returns (uint256) { return _allowance[owner][spender]; } /** * @dev See {IERC20-approve}. */ function approve(address spender, uint256 wad) external virtual override returns (bool) { return _setAllowance(msg.sender, spender, wad); } /** * @dev See {IERC20-transfer}. * * Requirements: * * - the caller must have a balance of at least `wad`. */ function transfer(address dst, uint256 wad) external virtual override returns (bool) { return _transfer(msg.sender, dst, wad); } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `src` must have a balance of at least `wad`. * - the caller is not `src`, it must have allowance for ``src``'s tokens of at least * `wad`. */ /// if_succeeds {:msg "TransferFrom - decrease allowance"} msg.sender != src ==> old(_allowance[src][msg.sender]) >= wad; function transferFrom( address src, address dst, uint256 wad ) external virtual override returns (bool) { _decreaseAllowance(src, wad); return _transfer(src, dst, wad); } /** * @dev Moves tokens `wad` from `src` to `dst`. * * Emits a {Transfer} event. * * Requirements: * * - `src` must have a balance of at least `amount`. */ /// if_succeeds {:msg "Transfer - src decrease"} old(_balanceOf[src]) >= _balanceOf[src]; /// if_succeeds {:msg "Transfer - dst increase"} _balanceOf[dst] >= old(_balanceOf[dst]); /// if_succeeds {:msg "Transfer - supply"} old(_balanceOf[src]) + old(_balanceOf[dst]) == _balanceOf[src] + _balanceOf[dst]; function _transfer( address src, address dst, uint256 wad ) internal virtual returns (bool) { require(_balanceOf[src] >= wad, 'ERC20: Insufficient balance'); unchecked { _balanceOf[src] = _balanceOf[src] - wad; } _balanceOf[dst] = _balanceOf[dst] + wad; emit Transfer(src, dst, wad); return true; } /** * @dev Sets the allowance granted to `spender` by `owner`. * * Emits an {Approval} event indicating the updated allowance. */ function _setAllowance( address owner, address spender, uint256 wad ) internal virtual returns (bool) { _allowance[owner][spender] = wad; emit Approval(owner, spender, wad); return true; } /** * @dev Decreases the allowance granted to the caller by `src`, unless src == msg.sender or _allowance[src][msg.sender] == MAX * * Emits an {Approval} event indicating the updated allowance, if the allowance is updated. * * Requirements: * * - `spender` must have allowance for the caller of at least * `wad`, unless src == msg.sender */ /// if_succeeds {:msg "Decrease allowance - underflow"} old(_allowance[src][msg.sender]) <= _allowance[src][msg.sender]; function _decreaseAllowance(address src, uint256 wad) internal virtual returns (bool) { if (src != msg.sender) { uint256 allowed = _allowance[src][msg.sender]; if (allowed != type(uint256).max) { require(allowed >= wad, 'ERC20: Insufficient approval'); unchecked { _setAllowance(src, msg.sender, allowed - wad); } } } return true; } /** @dev Creates `wad` tokens and assigns them to `dst`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. */ /// if_succeeds {:msg "Mint - balance overflow"} old(_balanceOf[dst]) >= _balanceOf[dst]; /// if_succeeds {:msg "Mint - supply overflow"} old(_totalSupply) >= _totalSupply; function _mint(address dst, uint256 wad) internal virtual returns (bool) { _balanceOf[dst] = _balanceOf[dst] + wad; _totalSupply = _totalSupply + wad; emit Transfer(address(0), dst, wad); return true; } /** * @dev Destroys `wad` tokens from `src`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `src` must have at least `wad` tokens. */ /// if_succeeds {:msg "Burn - balance underflow"} old(_balanceOf[src]) <= _balanceOf[src]; /// if_succeeds {:msg "Burn - supply underflow"} old(_totalSupply) <= _totalSupply; function _burn(address src, uint256 wad) internal virtual returns (bool) { unchecked { require(_balanceOf[src] >= wad, 'ERC20: Insufficient balance'); _balanceOf[src] = _balanceOf[src] - wad; _totalSupply = _totalSupply - wad; emit Transfer(src, address(0), wad); } return true; } }
// SPDX-License-Identifier: MIT // Adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/53516bc555a454862470e7860a9b5254db4d00f5/contracts/token/ERC20/ERC20Permit.sol pragma solidity 0.8.16; import 'src/tokens/ERC20.sol'; import 'src/interfaces/IERC2612.sol'; /** * @dev Extension of {ERC20} that allows token holders to use their tokens * without sending any transactions by setting {IERC20-allowance} with a * signature using the {permit} method, and then spend them via * {IERC20-transferFrom}. * * The {permit} signature mechanism conforms to the {IERC2612} interface. */ abstract contract ERC20Permit is ERC20, IERC2612 { mapping(address => uint256) public override nonces; bytes32 public immutable PERMIT_TYPEHASH = keccak256( 'Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)' ); bytes32 private immutable _DOMAIN_SEPARATOR; uint256 public immutable deploymentChainId; constructor( string memory name_, string memory symbol_, uint8 decimals_ ) ERC20(name_, symbol_, decimals_) { deploymentChainId = block.chainid; _DOMAIN_SEPARATOR = _calculateDomainSeparator(block.chainid); } /// @dev Calculate the DOMAIN_SEPARATOR. function _calculateDomainSeparator(uint256 chainId) private view returns (bytes32) { return keccak256( abi.encode( keccak256( 'EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)' ), keccak256(bytes(name)), keccak256(bytes(version())), chainId, address(this) ) ); } /// @dev Return the DOMAIN_SEPARATOR. function DOMAIN_SEPARATOR() external view returns (bytes32) { return block.chainid == deploymentChainId ? _DOMAIN_SEPARATOR : _calculateDomainSeparator(block.chainid); } /// @dev Setting the version as a function so that it can be overriden function version() public pure virtual returns (string memory) { return '1'; } /** * @dev See {IERC2612-permit}. * * In cases where the free option is not a concern, deadline can simply be * set to uint(-1), so it should be seen as an optional parameter */ function permit( address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external virtual override { require(deadline >= block.timestamp, 'ERC20Permit: expired deadline'); bytes32 hashStruct = keccak256( abi.encode( PERMIT_TYPEHASH, owner, spender, amount, nonces[owner]++, deadline ) ); bytes32 hash = keccak256( abi.encodePacked( '\x19\x01', block.chainid == deploymentChainId ? _DOMAIN_SEPARATOR : _calculateDomainSeparator(block.chainid), hashStruct ) ); address signer = ecrecover(hash, v, r, s); require( signer != address(0) && signer == owner, 'ERC20Permit: invalid signature' ); _setAllowance(owner, spender, amount); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.16; import 'src/tokens/ERC20Permit.sol'; import 'src/interfaces/IERC5095.sol'; import 'src/interfaces/IRedeemer.sol'; import 'src/interfaces/IMarketPlace.sol'; import 'src/interfaces/IYield.sol'; import 'src/errors/Exception.sol'; import 'src/lib/Cast.sol'; import 'src/lib/Safe.sol'; contract ERC5095 is ERC20Permit, IERC5095 { /// @dev unix timestamp when the ERC5095 token can be redeemed uint256 public immutable override maturity; /// @dev address of the ERC20 token that is returned on ERC5095 redemption address public immutable override underlying; /// @dev address of the minting authority address public immutable lender; /// @dev address of the "marketplace" YieldSpace AMM router address public immutable marketplace; ///@dev Interface to interact with the pool address public pool; /// @dev address and interface for an external custody contract (necessary for some project's backwards compatability) address public immutable redeemer; /// @notice ensures that only a certain address can call the function /// @param a address that msg.sender must be to be authorized modifier authorized(address a) { if (msg.sender != a) { revert Exception(0, 0, 0, msg.sender, a); } _; } constructor( address _underlying, uint256 _maturity, address _redeemer, address _lender, address _marketplace, string memory name_, string memory symbol_, uint8 decimals_ ) ERC20Permit(name_, symbol_, decimals_) { underlying = _underlying; maturity = _maturity; redeemer = _redeemer; lender = _lender; marketplace = _marketplace; pool = address(0); } /// @notice Allows the marketplace to set the pool /// @param p Address of the pool /// @return bool True if successful function setPool(address p) external authorized(marketplace) returns (bool) { pool = p; return true; } /// @notice Allows the marketplace to spend underlying, principal tokens held by the token /// @dev This is necessary when MarketPlace calls pool methods to swap tokens /// @return True if successful function approveMarketPlace() external authorized(marketplace) returns (bool) { // Approve the marketplace to spend the token's underlying Safe.approve(IERC20(underlying), marketplace, type(uint256).max); // Approve the marketplace to spend illuminate PTs Safe.approve(IERC20(address(this)), marketplace, type(uint256).max); return true; } /// @notice Post or at maturity, converts an amount of principal tokens to an amount of underlying that would be returned. /// @param s The amount of principal tokens to convert /// @return uint256 The amount of underlying tokens returned by the conversion function convertToUnderlying(uint256 s) external view override returns (uint256) { if (block.timestamp < maturity) { return previewRedeem(s); } return s; } /// @notice Post or at maturity, converts a desired amount of underlying tokens returned to principal tokens needed. /// @param a The amount of underlying tokens to convert /// @return uint256 The amount of principal tokens returned by the conversion function convertToShares(uint256 a) external view override returns (uint256) { if (block.timestamp < maturity) { return previewWithdraw(a); } return a; } /// @notice Returns user's PT balance /// @param o The address of the owner for which redemption is calculated /// @return uint256 The maximum amount of principal tokens that `owner` can redeem. function maxRedeem(address o) external view override returns (uint256) { return _balanceOf[o]; } /// @notice Post or at maturity, returns user's PT balance. Prior to maturity, returns a previewRedeem for owner's PT balance. /// @param o The address of the owner for which withdrawal is calculated /// @return uint256 maximum amount of underlying tokens that `owner` can withdraw. function maxWithdraw(address o) external view override returns (uint256) { if (block.timestamp < maturity) { return previewRedeem(_balanceOf[o]); } return _balanceOf[o]; } /// @notice After maturity, returns 0. Prior to maturity, returns the amount of `shares` when spending `a` in underlying on a YieldSpace AMM. /// @param a The amount of underlying spent /// @return uint256 The amount of PT purchased by spending `a` of underlying function previewDeposit(uint256 a) public view returns (uint256) { if (block.timestamp < maturity) { return IYield(pool).sellBasePreview(Cast.u128(a)); } return 0; } /// @notice After maturity, returns 0. Prior to maturity, returns the amount of `assets` in underlying spent on a purchase of `s` in PT on a YieldSpace AMM. /// @param s The amount of principal tokens bought in the simulation /// @return uint256 The amount of underlying required to purchase `s` of PT function previewMint(uint256 s) public view returns (uint256) { if (block.timestamp < maturity) { return IYield(pool).buyFYTokenPreview(Cast.u128(s)); } return 0; } /// @notice Post or at maturity, simulates the effects of redemption. Prior to maturity, returns the amount of `assets` from a sale of `s` PTs on a YieldSpace AMM. /// @param s The amount of principal tokens redeemed in the simulation /// @return uint256 The amount of underlying returned by `s` of PT redemption function previewRedeem(uint256 s) public view override returns (uint256) { if (block.timestamp >= maturity) { // After maturity, the amount redeemed is based on the Redeemer contract's holdings of the underlying return Cast.u128( s * Cast.u128( IRedeemer(redeemer).holdings(underlying, maturity) ) ) / _totalSupply; } // Prior to maturity, return a a preview of a swap on the pool return IYield(pool).sellFYTokenPreview(Cast.u128(s)); } /// @notice Post or at maturity, simulates the effects of withdrawal at the current block. Prior to maturity, simulates the amount of PTs necessary to receive `a` in underlying from the sale of PTs on a YieldSpace AMM. /// @param a The amount of underlying tokens withdrawn in the simulation /// @return uint256 The amount of principal tokens required for the withdrawal of `a` function previewWithdraw(uint256 a) public view override returns (uint256) { if (block.timestamp >= maturity) { // After maturity, the amount redeemed is based on the Redeemer contract's holdings of the underlying return (a * _totalSupply) / IRedeemer(redeemer).holdings(underlying, maturity); } // Prior to maturity, return a a preview of a swap on the pool return IYield(pool).buyBasePreview(Cast.u128(a)); } /// @notice Before maturity spends `a` of underlying, and sends PTs to `r`. Post or at maturity, reverts. /// @param a The amount of underlying tokens deposited /// @param r The receiver of the principal tokens /// @param m Minimum number of shares that the user will receive /// @return uint256 The amount of principal tokens purchased function deposit( uint256 a, address r, uint256 m ) external returns (uint256) { // Execute the deposit return _deposit(r, a, m); } /// @notice Before maturity spends `assets` of underlying, and sends `shares` of PTs to `receiver`. Post or at maturity, reverts. /// @param a The amount of underlying tokens deposited /// @param r The receiver of the principal tokens /// @return uint256 The amount of principal tokens burnt by the withdrawal function deposit(uint256 a, address r) external override returns (uint256) { // Execute the deposit return _deposit(r, a, 0); } /// @notice Before maturity mints `s` of PTs to `r` by spending underlying. Post or at maturity, reverts. /// @param s The amount of shares being minted /// @param r The receiver of the underlying tokens being withdrawn /// @param m Maximum amount of underlying that the user will spend /// @return uint256 The amount of principal tokens purchased function mint( uint256 s, address r, uint256 m ) external returns (uint256) { // Execute the mint return _mint(r, s, m); } /// @notice Before maturity mints `shares` of PTs to `receiver` by spending underlying. Post or at maturity, reverts. /// @param s The amount of shares being minted /// @param r The receiver of the underlying tokens being withdrawn /// @return uint256 The amount of principal tokens purchased function mint(uint256 s, address r) external override returns (uint256) { // Execute the mint return _mint(r, s, type(uint128).max); } /// @notice At or after maturity, burns PTs from owner and sends `a` underlying to `r`. Before maturity, sends `a` by selling shares of PT on a YieldSpace AMM. /// @param a The amount of underlying tokens withdrawn /// @param r The receiver of the underlying tokens being withdrawn /// @param o The owner of the underlying tokens /// @param m Maximum amount of PTs to be sold /// @return uint256 The amount of principal tokens burnt by the withdrawal function withdraw( uint256 a, address r, address o, uint256 m ) external returns (uint256) { // Execute the withdrawal return _withdraw(a, r, o, m); } /// @notice At or after maturity, burns PTs from owner and sends `a` underlying to `r`. Before maturity, sends `a` by selling shares of PT on a YieldSpace AMM. /// @param a The amount of underlying tokens withdrawn /// @param r The receiver of the underlying tokens being withdrawn /// @param o The owner of the underlying tokens /// @return uint256 The amount of principal tokens burnt by the withdrawal function withdraw( uint256 a, address r, address o ) external override returns (uint256) { // Execute the withdrawal return _withdraw(a, r, o, type(uint128).max); } /// @notice At or after maturity, burns exactly `s` of Principal Tokens from `o` and sends underlying tokens to `r`. Before maturity, sends underlying by selling `s` of PT on a YieldSpace AMM. /// @param s The number of shares to be burned in exchange for the underlying asset /// @param r The receiver of the underlying tokens being withdrawn /// @param o Address of the owner of the shares being burned /// @param m Minimum amount of underlying that must be received /// @return uint256 The amount of underlying tokens distributed by the redemption function redeem( uint256 s, address r, address o, uint256 m ) external returns (uint256) { // Execute the redemption return _redeem(s, r, o, m); } /// @notice At or after maturity, burns exactly `shares` of Principal Tokens from `owner` and sends `assets` of underlying tokens to `receiver`. Before maturity, sells `s` of PT on a YieldSpace AMM. /// @param s The number of shares to be burned in exchange for the underlying asset /// @param r The receiver of the underlying tokens being withdrawn /// @param o Address of the owner of the shares being burned /// @return uint256 The amount of underlying tokens distributed by the redemption function redeem( uint256 s, address r, address o ) external override returns (uint256) { // Execute the redemption return _redeem(s, r, o, 0); } /// @param f Address to burn from /// @param a Amount to burn /// @return bool true if successful function authBurn(address f, uint256 a) external authorized(redeemer) returns (bool) { _burn(f, a); return true; } /// @param t Address recieving the minted amount /// @param a The amount to mint /// @return bool True if successful function authMint(address t, uint256 a) external authorized(lender) returns (bool) { _mint(t, a); return true; } /// @param o Address of the owner of the tokens /// @param s Address of the spender /// @param a Amount to be approved function authApprove( address o, address s, uint256 a ) external authorized(redeemer) returns (bool) { _allowance[o][s] = a; return true; } function _deposit( address r, uint256 a, uint256 m ) internal returns (uint256) { // Revert if called at or after maturity if (block.timestamp >= maturity) { revert Exception( 21, block.timestamp, maturity, address(0), address(0) ); } // Receive the funds from the sender Safe.transferFrom(IERC20(underlying), msg.sender, address(this), a); // Sell the underlying assets for PTs uint128 returned = IMarketPlace(marketplace).sellUnderlying( underlying, maturity, Cast.u128(a), Cast.u128(m) ); // Pass the received shares onto the intended receiver _transfer(address(this), r, returned); return returned; } function _mint( address r, uint256 s, uint256 m ) internal returns (uint256) { // Revert if called at or after maturity if (block.timestamp >= maturity) { revert Exception( 21, block.timestamp, maturity, address(0), address(0) ); } // Determine how many underlying tokens are needed to mint the shares uint256 required = IYield(pool).buyFYTokenPreview(Cast.u128(s)); // Transfer the underlying to the token Safe.transferFrom( IERC20(underlying), msg.sender, address(this), required ); // Swap the underlying for principal tokens via the pool uint128 sold = IMarketPlace(marketplace).buyPrincipalToken( underlying, maturity, Cast.u128(s), Cast.u128(m) ); // Transfer the principal tokens to the desired receiver _transfer(address(this), r, s); return sold; } function _withdraw( uint256 a, address r, address o, uint256 m ) internal returns (uint256) { // Determine how many principal tokens are needed to purchase the underlying uint256 needed = previewWithdraw(a); // Pre maturity if (block.timestamp < maturity) { // Receive the shares from the caller _transfer(o, address(this), needed); // If owner is the sender, sell PT without allowance check if (o == msg.sender) { uint128 returned = IMarketPlace(marketplace).buyUnderlying( underlying, maturity, Cast.u128(a), Cast.u128(m) ); // Transfer the underlying to the desired receiver Safe.transfer(IERC20(underlying), r, a); return returned; } else { // Else, sell PT with allowance check // Get the allowance of the user spending the tokens uint256 allowance = _allowance[o][msg.sender]; // Check for sufficient allowance if (allowance < needed) { revert Exception(20, allowance, a, address(0), address(0)); } // Update the caller's allowance _allowance[o][msg.sender] = allowance - needed; // Sell the principal tokens for underlying uint128 returned = IMarketPlace(marketplace).buyUnderlying( underlying, maturity, Cast.u128(a), Cast.u128(m) ); // Transfer the underlying to the desired receiver Safe.transfer(IERC20(underlying), r, returned); return returned; } } // Post maturity else { // If owner is the sender, redeem PT without allowance check if (o == msg.sender) { // Execute the redemption to the desired receiver return IRedeemer(redeemer).authRedeem( underlying, maturity, msg.sender, r, needed ); } else { // Get the allowance of the user spending the tokens uint256 allowance = _allowance[o][msg.sender]; // Check for sufficient allowance if (allowance < needed) { revert Exception( 20, allowance, needed, address(0), address(0) ); } // Update the callers's allowance _allowance[o][msg.sender] = allowance - needed; // Execute the redemption to the desired receiver return IRedeemer(redeemer).authRedeem( underlying, maturity, o, r, needed ); } } } function _redeem( uint256 s, address r, address o, uint256 m ) internal returns (uint256) { // Pre-maturity if (block.timestamp < maturity) { // Receive the funds from the user _transfer(o, address(this), s); // If owner is the sender, sell PT without allowance check if (o == msg.sender) { // Swap principal tokens for the underlying asset uint128 returned = IMarketPlace(marketplace).sellPrincipalToken( underlying, maturity, Cast.u128(s), Cast.u128(m) ); // Transfer underlying to the desired receiver Safe.transfer(IERC20(underlying), r, returned); return returned; // Else, sell PT with allowance check } else { // Get the allowance of the user spending the tokens uint256 allowance = _allowance[o][msg.sender]; // Check for sufficient allowance if (allowance < s) { revert Exception(20, allowance, s, address(0), address(0)); } // Update the caller's allowance _allowance[o][msg.sender] = allowance - s; // Sell the principal tokens for the underlying uint128 returned = IMarketPlace(marketplace).sellPrincipalToken( underlying, maturity, Cast.u128(s), Cast.u128(m) ); // Transfer the underlying to the desired receiver Safe.transfer(IERC20(underlying), r, returned); return returned; } // Post-maturity } else { // If owner is the sender, redeem PT without allowance check if (o == msg.sender) { // Execute the redemption to the desired receiver return IRedeemer(redeemer).authRedeem( underlying, maturity, msg.sender, r, s ); } else { // Get the allowance of the user spending the tokens uint256 allowance = _allowance[o][msg.sender]; // Check for sufficient allowance if (allowance < s) { revert Exception(20, allowance, s, address(0), address(0)); } // Update the caller's allowance _allowance[o][msg.sender] = allowance - s; // Execute the redemption to the desired receiver return IRedeemer(redeemer).authRedeem( underlying, maturity, o, r, s ); } } } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_underlying","type":"address"},{"internalType":"uint256","name":"_maturity","type":"uint256"},{"internalType":"address","name":"_redeemer","type":"address"},{"internalType":"address","name":"_lender","type":"address"},{"internalType":"address","name":"_marketplace","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"Exception","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"approveMarketPlace","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"o","type":"address"},{"internalType":"address","name":"s","type":"address"},{"internalType":"uint256","name":"a","type":"uint256"}],"name":"authApprove","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"f","type":"address"},{"internalType":"uint256","name":"a","type":"uint256"}],"name":"authBurn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"t","type":"address"},{"internalType":"uint256","name":"a","type":"uint256"}],"name":"authMint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"guy","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"s","type":"uint256"}],"name":"convertToUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deploymentChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"address","name":"r","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"address","name":"r","type":"address"},{"internalType":"uint256","name":"m","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketplace","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maturity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"o","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"o","type":"address"}],"name":"maxWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"s","type":"uint256"},{"internalType":"address","name":"r","type":"address"},{"internalType":"uint256","name":"m","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"s","type":"uint256"},{"internalType":"address","name":"r","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"s","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"s","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"s","type":"uint256"},{"internalType":"address","name":"r","type":"address"},{"internalType":"address","name":"o","type":"address"},{"internalType":"uint256","name":"m","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"s","type":"uint256"},{"internalType":"address","name":"r","type":"address"},{"internalType":"address","name":"o","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redeemer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"p","type":"address"}],"name":"setPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"address","name":"r","type":"address"},{"internalType":"address","name":"o","type":"address"},{"internalType":"uint256","name":"m","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"address","name":"r","type":"address"},{"internalType":"address","name":"o","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
61018080604052346200074d576200359c803803809162000021828562000752565b83398101906101009182828203126200074d576200003f8262000776565b91602081015191620000546040830162000776565b92620000636060840162000776565b91620000726080850162000776565b60a08501519094906001600160401b0381116200074d5782620000979183016200078b565b60c08201519092906001600160401b0381116200074d5760e091620000be9184016200078b565b9101519160ff831683036200074d57620000da60035462000802565b90601f918281116200071d575b506006623f3f3f60e81b01806003556200010360045462000802565b838111620006dc575b506004556005805460ff191660121790558051906001600160401b038211620004bf5781906200013e60035462000802565b848111620006a7575b506020908483116001146200062d5760009262000621575b50508160011b916000199060031b1c1916176003555b8151916001600160401b038311620004bf576200019460045462000802565b828111620005e1575b506020918311600114620005525760ff9392916000918362000546575b50508160011b916000199060031b1c1916176004555b1660ff1960055416176005557f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c96080524660c05260405194600060035496620002198862000802565b80825281602081019360019a8b81169081600014620005285750600114620004d5575b6200024a9250038262000752565b51902060408051919791908101906001600160401b03821181831017620004bf5760209160405282815201603160f81b815220956040519660208801917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8352604089015260608801524660808801523060a088015260a0875260c087019680881060018060401b03891117620004bf57604088905251902060a052865260e052610160928352610120908152610140918252600780546001600160a01b0319169055612d2394856200085986396080518581816108ba0152611647015260a05185818161093c01526116ea015260c0518581816109140152818161157e01526116c1015260e05185818161073201528181610a7c01528181610cf2015281816110470152818161143301528181611ca901528181611cdf01528181611d1201528181611d9401528181611e5201528181611f20015281816120bf0152818161234701528181612778015281816129c80152612b6d015251848181610ab901528181610c1101528181610d9401528181610ff1015281816110ea0152818161146e01528181611fd001528181612168015281816123a4015281816124e6015281816126080152818161270a015281816127cf015281816128730152818161292c01528181612a2801528181612ae401528181612b4101528181612bcf01528181612c670152612cc50152518381816105d6015261151701525182818161099801528181610b4701528181610e0f01528181610fbf0152818161136b015281816123f1015261252f01525181818161087201528181610f13015281816112300152818161201e015281816121a601526126340152f35b634e487b7160e01b600052604160045260246000fd5b506003600090815290918a6000805160206200357c8339815191525b8284106200050d575050509060206200024a928201016200023c565b6020929450805483858801015201910190918a8493620004f1565b60ff19168652506200024a92151560051b820160200190506200023c565b015190503880620001ba565b600460009081527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b929190601f198516905b818110620005c8575091600193918560ff97969410620005ae575b505050811b01600455620001d0565b015160001960f88460031b161c191690553880806200059f565b9293602060018192878601518155019501930162000584565b6200061090600460005260206000208480870160051c8201926020881062000617575b0160051c01906200083f565b386200019d565b9250819262000604565b0151905038806200015f565b600360009081526000805160206200357c8339815191529350601f198516905b8181106200068e575090846001959493921062000674575b505050811b0160035562000175565b015160001960f88460031b161c1916905538808062000665565b929360206001819287860151815501950193016200064d565b620006d590600360005260206000208680860160051c8201926020871062000617570160051c01906200083f565b3862000147565b60046000526200071690840160051c7f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b908101906200083f565b386200010c565b60036000526200074690830160051c6000805160206200357c833981519152908101906200083f565b38620000e7565b600080fd5b601f909101601f19168101906001600160401b03821190821017620004bf57604052565b51906001600160a01b03821682036200074d57565b919080601f840112156200074d578251906001600160401b038211620004bf5760405191602091620007c7601f8301601f191684018562000752565b8184528282870101116200074d5760005b818110620007ee57508260009394955001015290565b8581018301518482018401528201620007d8565b90600182811c9216801562000834575b60208310146200081e57565b634e487b7160e01b600052602260045260246000fd5b91607f169162000812565b8181106200084b575050565b600081556001016200083f56fe60806040526004361015610013575b600080fd5b60003560e01c806306fdde0314610352578063095ea7b3146103495780630a28a477146103405780630fa9d3b11461033757806316f0115b1461032e57806318160ddd146103255780631dc7f5211461031c578063204f83f91461031357806323b872dd1461030a5780632ba29d381461030157806330adf81f146102f8578063313ce567146102ef5780633644e515146102e65780634437152a146102dd5780634cdad506146102d457806354fd4d50146102cb5780636e553f65146102c25780636f307dc3146102b957806370a08231146101fc5780637ecebe00146102b0578063836a1040146102a757806388ba33df1461029e57806392450f201461029557806394bf804d1461028c57806395d89b41146102835780639b3906841461027a5780639f40a7b314610271578063a318c1a414610268578063a9059cbb1461025f578063abc8c7af14610256578063b3d7f6b91461024d578063b460af9414610244578063ba0876521461023b578063bc157ac114610232578063bcead63e14610229578063c6e6f59214610220578063cd0d009614610217578063ce96cb771461020e578063d505accf14610205578063d905777e146101fc578063dd62ed3e146101f35763ef8b30f7146101eb57600080fd5b61000e61181f565b5061000e6117c6565b5061000e610c40565b5061000e6115c5565b5061000e6115a1565b5061000e611565565b5061000e611546565b5061000e611500565b5061000e611422565b5061000e611408565b5061000e6113ee565b5061000e61139a565b5061000e611354565b5061000e61132b565b5061000e61130e565b5061000e6112f1565b5061000e61121f565b5061000e611177565b5061000e611027565b5061000e610fa3565b5061000e610ee9565b5061000e610ce0565b5061000e610c7b565b5061000e610bfa565b5061000e610a5d565b5061000e610a22565b5061000e610a03565b5061000e610973565b5061000e6108ff565b5061000e6108dd565b5061000e6108a1565b5061000e61085b565b5061000e61078a565b5061000e610719565b5061000e6106fa565b5061000e6106db565b5061000e6106b1565b5061000e6105ac565b5061000e610585565b5061000e610552565b5061000e610440565b90600182811c9216801561038b575b602083101461037557565b634e487b7160e01b600052602260045260246000fd5b91607f169161036a565b50634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff8211176103c857604052565b6103d0610395565b604052565b90601f8019910116810190811067ffffffffffffffff8211176103c857604052565b6020808252825181830181905290939260005b82811061042c57505060409293506000838284010152601f8019910116010190565b81810186015184820160400152850161040a565b503461000e576000806003193601126105235760405190806003546104648161035b565b808552916001918083169081156104f9575060011461049e575b61049a8561048e818703826103d5565b604051918291826103f7565b0390f35b9250600383527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b8284106104e157505050810160200161048e8261049a61047e565b805460208587018101919091529093019281016104c6565b86955061049a9693506020925061048e94915060ff191682840152151560051b820101929361047e565b80fd5b600435906001600160a01b038216820361000e57565b602435906001600160a01b038216820361000e57565b503461000e57604036600319011261000e57602061057b610571610526565b6024359033611954565b6040519015158152f35b503461000e57602036600319011261000e5760206105a46004356120bd565b604051908152f35b503461000e5760408060031936011261000e576105c7610526565b602435906001600160a01b03907f00000000000000000000000000000000000000000000000000000000000000008281163303610690575016907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef610669600092848452600160205285842054818101809111610683575b8585526001602052868520558354818101809111610676575b845585519081529081906020820190565b0390a35160018152602090f35b61067e61188a565b610658565b61068b61188a565b61063f565b8451636d4c6c8960e01b81529081906106ad903360048401611bcb565b0390fd5b503461000e57600036600319011261000e576007546040516001600160a01b039091168152602090f35b503461000e57600036600319011261000e576020600054604051908152f35b503461000e57602036600319011261000e5760206105a4600435611ca7565b503461000e57600036600319011261000e5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b606090600319011261000e576001600160a01b0390600435828116810361000e5791602435908116810361000e579060443590565b503461000e5761079936610755565b906001600160a01b0383163381036107cc575b61049a6107ba8484876118a1565b60405190151581529081906020820190565b600090815260026020908152604080832033845290915290205460018101156107ac5791908183106108165761049a9361080c836107ba95033383611954565b50935090916107ac565b60405162461bcd60e51b815260206004820152601c60248201527f45524332303a20496e73756666696369656e7420617070726f76616c000000006044820152606490fd5b503461000e57600036600319011261000e576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b503461000e57600036600319011261000e5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b503461000e57600036600319011261000e57602060ff60055416604051908152f35b503461000e57600036600319011261000e57467f0000000000000000000000000000000000000000000000000000000000000000036109635760207f0000000000000000000000000000000000000000000000000000000000000000604051908152f35b602061096e466119a7565b6105a4565b503461000e57602036600319011261000e5761098d610526565b6001600160a01b03907f000000000000000000000000000000000000000000000000000000000000000082811633036109e55750166bffffffffffffffffffffffff60a01b6007541617600755602060405160018152f35b604051636d4c6c8960e01b81529081906106ad903360048401611bcb565b503461000e57602036600319011261000e5760206105a4600435611f1e565b503461000e57600036600319011261000e5761049a604051610a43816103ac565b60018152603160f81b6020820152604051918291826103f7565b503461000e57604036600319011261000e57600435610a7a61053c565b7f00000000000000000000000000000000000000000000000000000000000000009182421015610bc6576001600160801b03610b4360208095610b83947f0000000000000000000000000000000000000000000000000000000000000000916000610af960018060a01b0393610af4813033888a16612273565b611e3c565b60405162771d7560e11b81526001600160a01b03909516600486015260248501929092526001600160801b0390911660448401526000606484015291938492839182906084820190565b03927f0000000000000000000000000000000000000000000000000000000000000000165af1908115610bb9575b600091610b8c575b50168092306118a1565b50604051908152f35b610bac9150853d8111610bb2575b610ba481836103d5565b810190611d73565b38610b79565b503d610b9a565b610bc1611b72565b610b71565b604051636d4c6c8960e01b81526015600482015242602482015260448101849052600060648201819052608482015260a490fd5b503461000e57600036600319011261000e576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b503461000e57602036600319011261000e576001600160a01b03610c62610526565b1660005260016020526020604060002054604051908152f35b503461000e57602036600319011261000e576001600160a01b03610c9d610526565b1660005260066020526020604060002054604051908152f35b606090600319011261000e57600435906024356001600160a01b038116810361000e579060443590565b503461000e57610cef36610cb6565b917f00000000000000000000000000000000000000000000000000000000000000009081421015610eb557600754610d3d90610d31906001600160a01b031681565b6001600160a01b031690565b92610d7d610d4a83611e3c565b60405163fdb0732d60e01b81526001600160801b0390911660048201526020969095879283918891829081906024820190565b03915afa958615610ea8575b600096610e89575b507f0000000000000000000000000000000000000000000000000000000000000000956001600160801b03956001600160a01b0391610dd69088163033858c16612273565b6000610dea610de488611e3c565b94611e3c565b98610e0b6040519a8b9687958694636ba06f1b60e01b865260048601612241565b03927f0000000000000000000000000000000000000000000000000000000000000000165af1938415610e7c575b600094610e57575b5090610e4d91306118a1565b5060405191168152f35b610e4d92919450610e7490863d8811610bb257610ba481836103d5565b939091610e41565b610e84611b72565b610e39565b610ea1919650823d8411610bb257610ba481836103d5565b9438610d91565b610eb0611b72565b610d89565b604051636d4c6c8960e01b81526015600482015242602482015260448101839052600060648201819052608482015260a490fd5b503461000e5760408060031936011261000e57610f04610526565b602435906001600160a01b03907f000000000000000000000000000000000000000000000000000000000000000082811633036106905750167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6106696000938385526001602052610f7b8187872054101561183e565b8385526001602052808686205403868620558085540385558551918291829190602083019252565b503461000e57600036600319011261000e576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081811633036109e5576110168161101c937f000000000000000000000000000000000000000000000000000000000000000016611bf9565b30611bf9565b602060405160018152f35b503461000e57604036600319011261000e5760043561104461053c565b907f00000000000000000000000000000000000000000000000000000000000000009081421015610eb557600754610e0b92919061108c90610d31906001600160a01b031681565b936110ca61109983611e3c565b60405163fdb0732d60e01b81526001600160801b039091166004820152602096879283918391829081906024820190565b03915afa90811561116a575b60009161114d575b506001600160801b03947f0000000000000000000000000000000000000000000000000000000000000000916001600160a01b0391906111249088163033858716612273565b600061112f87611e3c565b604051636ba06f1b60e01b8152998a95869485939160048501612213565b6111649150823d8411610bb257610ba481836103d5565b386110de565b611172611b72565b6110d6565b503461000e5760008060031936011261052357604051908060045461119b8161035b565b808552916001918083169081156104f957506001146111c45761049a8561048e818703826103d5565b9250600483527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b82841061120757505050810160200161048e8261049a61047e565b805460208587018101919091529093019281016111ec565b503461000e5761122e36610755565b7f0000000000000000000000000000000000000000000000000000000000000000929091906001600160a01b0390818516330361129c5761129093945016600052600260205260406000209060018060a01b0316600052602052604060002090565b55602060405160018152f35b604051636d4c6c8960e01b8152806106ad873360048401611bcb565b608090600319011261000e57600435906001600160a01b0390602435828116810361000e5791604435908116810361000e579060643590565b503461000e5760206105a4611305366112b8565b92919091612b69565b503461000e5760206105a4611322366112b8565b92919091612768565b503461000e57604036600319011261000e57602061057b61134a610526565b60243590336118a1565b503461000e57600036600319011261000e576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b503461000e57602036600319011261000e5760206105a4600435611e50565b606090600319011261000e57600435906001600160a01b0390602435828116810361000e5791604435908116810361000e5790565b503461000e5760206105a4611402366113b9565b9161233b565b503461000e5760206105a461141c366113b9565b916129c5565b503461000e5761143136610cb6565b7f000000000000000000000000000000000000000000000000000000000000000092834210156114cc5760209384610b83936001600160801b03937f00000000000000000000000000000000000000000000000000000000000000009360006114ac610de460018060a01b0394610af4813033898d16612273565b95610b436040519788968795869462771d7560e11b865260048601612241565b604051636d4c6c8960e01b81526015600482015242602482015260448101859052600060648201819052608482015260a490fd5b503461000e57600036600319011261000e576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b503461000e57602036600319011261000e5760206105a4600435611cdd565b503461000e57600036600319011261000e5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b503461000e57602036600319011261000e5760206105a46115c0610526565b611d10565b503461000e5760e036600319011261000e576115df610526565b6115e761053c565b604435906064359260843560ff8116810361000e5760006020916116a761173161173d61179c9961161a42821015611b0a565b6001600160a01b03881660009081526006602052604090209081549161163f83611b56565b9055604080517f00000000000000000000000000000000000000000000000000000000000000008a82019081526001600160a01b03808d1660208301528d1692810192909252606082018d9052608082019390935260a08101919091529093849060c0830190565b03936116bb601f19958681018352826103d5565b519020927f0000000000000000000000000000000000000000000000000000000000000000461486146117b7577f0000000000000000000000000000000000000000000000000000000000000000935b6040519384918983019687909160429261190160f01b8352600283015260228201520190565b039081018352826103d5565b5190206040805191825260ff92909216602082015260a4359181019190915260c435606082015281805260809060015afa156117aa575b600051611797906001600160a01b03908116801515918261179e575b5050611b7f565b611954565b005b84161490503880611790565b6117b2611b72565b611774565b6117c0466119a7565b9361170b565b503461000e57604036600319011261000e5760206118166117e5610526565b6117ed61053c565b6001600160a01b0391821660009081526002855260408082209290931681526020919091522090565b54604051908152f35b503461000e57602036600319011261000e5760206105a4600435611d92565b1561184557565b60405162461bcd60e51b815260206004820152601b60248201527f45524332303a20496e73756666696369656e742062616c616e636500000000006044820152606490fd5b50634e487b7160e01b600052601160045260246000fd5b60207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9160018060a01b038091169384600052600183526118e986604060002054101561183e565b60008581526001808552604080832080548a900390556001600160a01b0384168352602091909152902054868101809111611947575b6001600160a01b03821660009081526001602052604090205b556040519586521693a3600190565b61194f61188a565b61191f565b6001600160a01b0390811660008181526002602090815260408083208686168452825290912091937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259391928690611938565b604051600354600092916119ba8261035b565b9384825260209485830193600190878282169182600014611acd575050600114611a6a575b5050906119f281611a64949303826103d5565b51902092611a56611a01611aed565b805190830120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f948101948552602085019790975283015260608201939093523060808201529291829060a0850190565b03601f1981018352826103d5565b51902090565b86919493925060036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b946000915b818310611ab65750939450919250908201016119f2826119df565b865485840185015295860195889390920191611a9b565b60ff1916875292151560051b850190920192506119f291508390506119df565b60405190611afa826103ac565b60018252603160f81b6020830152565b15611b1157565b60405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606490fd5b6001906000198114611b66570190565b611b6e61188a565b0190565b506040513d6000823e3d90fd5b15611b8657565b60405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606490fd5b60008082526020820181905260408201526001600160a01b0391821660608201529116608082015260a00190565b60405163095ea7b360e01b81526001600160a01b0390921660048301526000196024830152611c3391600091829160449183905af1611c70565b15611c3a57565b60405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b6044820152606490fd5b6000903d9015611ca0579081602014611c93575015611c8e57600090565b600190565b9050602081803e51151590565b908181803efd5b7f00000000000000000000000000000000000000000000000000000000000000004210611cd15790565b611cda90611f1e565b90565b7f00000000000000000000000000000000000000000000000000000000000000004210611d075790565b611cda906120bd565b7f00000000000000000000000000000000000000000000000000000000000000004210611d52576001600160a01b031660009081526001602052604090205490565b6001600160a01b0316600090815260016020526040902054611cda90611f1e565b9081602091031261000e57516001600160801b038116810361000e5790565b7f00000000000000000000000000000000000000000000000000000000000000004210611dbf5750600090565b6007546001600160a01b031690602490602090611ddb90611e3c565b92604051928380926304f9ef2360e21b82526001600160801b0380971660048301525afa908115611e2f575b600091611e1357501690565b611e2b915060203d8111610bb257610ba481836103d5565b1690565b611e37611b72565b611e07565b6001600160801b039081811161000e571690565b7f00000000000000000000000000000000000000000000000000000000000000004210611e7d5750600090565b6007546001600160a01b031690602490602090611e9990611e3c565b926040519283809263fdb0732d60e01b82526001600160801b0380971660048301525afa908115611e2f57600091611e1357501690565b9081602091031261000e575190565b8060001904821181151516611ef2570290565b611efa61188a565b0290565b8115611f08570490565b634e487b7160e01b600052601260045260246000fd5b7f000000000000000000000000000000000000000000000000000000000000000080421015611fb95750611fa260206001600160801b0392611f76611f70610d31610d3160075460018060a01b031690565b91611e3c565b6040516327bab06360e01b81526001600160801b03909116600482015292839190829081906024820190565b03915afa908115611e2f57600091611e1357501690565b6040516391b46a9160e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048201526024810191909152611cda9161207091610af4919061206a9061205e90602081806044810103817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156120b0575b600091612082575b50611e3c565b6001600160801b031690565b90611edf565b6001600160801b036000549116611efe565b6120a3915060203d81116120a9575b61209b81836103d5565b810190611ed0565b38612058565b503d612091565b6120b8611b72565b612050565b7f00000000000000000000000000000000000000000000000000000000000000008042101561213b5750611fa260206001600160801b039261210f611f70610d31610d3160075460018060a01b031690565b60405163b0f2892160e01b81526001600160801b03909116600482015292839190829081906024820190565b6121a2906020612151611cda9460005490611edf565b6040516391b46a9160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016600482015260248101939093529192839081906044820190565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa918215612206575b6000926121e6575b50611efe565b6121ff91925060203d81116120a95761209b81836103d5565b90386121e0565b61220e611b72565b6121d8565b606091949392608082019560018060a01b0316825260208201526001600160801b0380931660408201520152565b6001600160a01b03909116815260208101919091526001600160801b0391821660408201529116606082015260800190565b600092836064926122af968295604051946323b872dd60e01b865260018060a01b03809216600487015216602485015260448401525af1611c70565b156122b657565b60405162461bcd60e51b81526020600482015260146024820152731d1c985b9cd9995c88199c9bdb4819985a5b195960621b6044820152606490fd5b919082039182116122ff57565b61230761188a565b565b6001600160a01b0391821681526020810192909252918216604082015291166060820152608081019190915260a00190565b90612345826120bd565b7f0000000000000000000000000000000000000000000000000000000000000000938442106000146125cd5761237c8230836118a1565b506001600160a01b0391818316330361245e575050916123ea916001600160801b03949360207f0000000000000000000000000000000000000000000000000000000000000000956123cd85611e3c565b604051637ef1c17560e11b81529687928392908a60048501612213565b03816000857f0000000000000000000000000000000000000000000000000000000000000000165af1938415612451575b60009461242f575b50611e2b939416612954565b611e2b945061244b9060203d8111610bb257610ba481836103d5565b93612423565b612459611b72565b61241b565b6001600160a01b03821660009081526002602052604090209295926124979033905b9060018060a01b0316600052602052604060002090565b5481811061259757611cda9594936001600160801b03936124e06124c0612528956020956122f2565b6001600160a01b0390921660009081526002602052604090203390612480565b5561250b7f000000000000000000000000000000000000000000000000000000000000000096611e3c565b604051637ef1c17560e11b81529384928392908960048501612213565b038160008a7f0000000000000000000000000000000000000000000000000000000000000000165af190811561258a575b60009161256c575b501693849216612954565b612584915060203d8111610bb257610ba481836103d5565b38612561565b612592611b72565b612559565b604051636d4c6c8960e01b815260146004820152602481019190915260448101869052600060648201819052608482015260a490fd5b6001600160a01b039594919350858116330361268e5750936020929160006126309596604051968795869485936370a03ced60e01b855233907f000000000000000000000000000000000000000000000000000000000000000060048701612309565b03927f0000000000000000000000000000000000000000000000000000000000000000165af1908115612681575b600091612669575090565b611cda915060203d81116120a95761209b81836103d5565b612689611b72565b61265e565b6001600160a01b03811660009081526002602052604090209195916126b4903390612480565b54848110612732578495966126cd6020966000936122f2565b6001600160a01b03841660009081526002602052604090206126f0903390612480565b55612630604051978896879586946370a03ced60e01b86527f000000000000000000000000000000000000000000000000000000000000000060048701612309565b604051636d4c6c8960e01b815260146004820152602481019190915260448101859052600060648201819052608482015260a490fd5b92919092612775816120bd565b937f0000000000000000000000000000000000000000000000000000000000000000928342106000146128ee576127ad8630836118a1565b506001600160a01b0395818716330361281b5750506001600160801b039460207f0000000000000000000000000000000000000000000000000000000000000000956127fb611f7086611e3c565b956123ea6040519788938493637ef1c17560e11b85528b60048601612241565b6001600160a01b03821660009081526002602052604090209395929493612843903390612480565b548181106128b85792611cda9695949261286a6124c06020946001600160801b03976122f2565b55612898611f707f000000000000000000000000000000000000000000000000000000000000000097611e3c565b926125286040519485938493637ef1c17560e11b85528a60048601612241565b604051636d4c6c8960e01b815260146004820152602481019190915260448101879052600060648201819052608482015260a490fd5b6001600160a01b039695945090929150858116330361268e5750936020929160006126309596604051968795869485936370a03ced60e01b855233907f000000000000000000000000000000000000000000000000000000000000000060048701612309565b6044600092838093612987966040519363a9059cbb60e01b855260018060a01b0316600485015260248401525af1611c70565b1561298e57565b60405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b907f0000000000000000000000000000000000000000000000000000000000000000804210600014612b09576129fc8330866118a1565b506001600160a01b03938085163303612a925750906001600160801b036125286020611cda9594612a4d7f000000000000000000000000000000000000000000000000000000000000000096611e3c565b60405163d744e26960e01b81526001600160a01b038816600482015260248101929092526001600160801b031660448201526000606482015291829081906084820190565b6001600160a01b0381166000908152600260205260409020612ab5903390612480565b548481106127325760208594936001600160801b0393612ade6124c0611cda99612528966122f2565b55612a4d7f000000000000000000000000000000000000000000000000000000000000000096611e3c565b6001600160a01b039493858116330361268e5750936020929160006126309596604051968795869485936370a03ced60e01b855233907f000000000000000000000000000000000000000000000000000000000000000060048701612309565b91927f000000000000000000000000000000000000000000000000000000000000000090814210600014612c8c57612ba28430876118a1565b506001600160a01b03948086163303612c145750611cda93929160206001600160801b0392612bf4611f707f000000000000000000000000000000000000000000000000000000000000000097611e3c565b92612528604051948593849363d744e26960e01b85528a60048601612241565b6001600160a01b0381166000908152600260205260409020612c37903390612480565b54858110612597576001600160801b039286959492612c5e6124c0611cda996020956122f2565b55612bf4611f707f000000000000000000000000000000000000000000000000000000000000000097611e3c565b506001600160a01b039493858116330361268e5750936020929160006126309596604051968795869485936370a03ced60e01b855233907f00000000000000000000000000000000000000000000000000000000000000006004870161230956fea26469706673582212208530e193d9391de7f27e9397e62718fc6cde8627999f6fa7228b7435e6f7b91564736f6c63430008100033c2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000064a20f800000000000000000000000004ea57ef203e91ae8c7d9822aa09cc719a9c01ac6000000000000000000000000429b47c4aeadd42bbcb118651c8984086bfc4551000000000000000000000000cd1d02fda51cd24123e857ce94e4356d5c073b3f0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000012697074555344432d313638383334323430300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d697074555344432d4a554e323300000000000000000000000000000000000000
Deployed Bytecode
0x60806040526004361015610013575b600080fd5b60003560e01c806306fdde0314610352578063095ea7b3146103495780630a28a477146103405780630fa9d3b11461033757806316f0115b1461032e57806318160ddd146103255780631dc7f5211461031c578063204f83f91461031357806323b872dd1461030a5780632ba29d381461030157806330adf81f146102f8578063313ce567146102ef5780633644e515146102e65780634437152a146102dd5780634cdad506146102d457806354fd4d50146102cb5780636e553f65146102c25780636f307dc3146102b957806370a08231146101fc5780637ecebe00146102b0578063836a1040146102a757806388ba33df1461029e57806392450f201461029557806394bf804d1461028c57806395d89b41146102835780639b3906841461027a5780639f40a7b314610271578063a318c1a414610268578063a9059cbb1461025f578063abc8c7af14610256578063b3d7f6b91461024d578063b460af9414610244578063ba0876521461023b578063bc157ac114610232578063bcead63e14610229578063c6e6f59214610220578063cd0d009614610217578063ce96cb771461020e578063d505accf14610205578063d905777e146101fc578063dd62ed3e146101f35763ef8b30f7146101eb57600080fd5b61000e61181f565b5061000e6117c6565b5061000e610c40565b5061000e6115c5565b5061000e6115a1565b5061000e611565565b5061000e611546565b5061000e611500565b5061000e611422565b5061000e611408565b5061000e6113ee565b5061000e61139a565b5061000e611354565b5061000e61132b565b5061000e61130e565b5061000e6112f1565b5061000e61121f565b5061000e611177565b5061000e611027565b5061000e610fa3565b5061000e610ee9565b5061000e610ce0565b5061000e610c7b565b5061000e610bfa565b5061000e610a5d565b5061000e610a22565b5061000e610a03565b5061000e610973565b5061000e6108ff565b5061000e6108dd565b5061000e6108a1565b5061000e61085b565b5061000e61078a565b5061000e610719565b5061000e6106fa565b5061000e6106db565b5061000e6106b1565b5061000e6105ac565b5061000e610585565b5061000e610552565b5061000e610440565b90600182811c9216801561038b575b602083101461037557565b634e487b7160e01b600052602260045260246000fd5b91607f169161036a565b50634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff8211176103c857604052565b6103d0610395565b604052565b90601f8019910116810190811067ffffffffffffffff8211176103c857604052565b6020808252825181830181905290939260005b82811061042c57505060409293506000838284010152601f8019910116010190565b81810186015184820160400152850161040a565b503461000e576000806003193601126105235760405190806003546104648161035b565b808552916001918083169081156104f9575060011461049e575b61049a8561048e818703826103d5565b604051918291826103f7565b0390f35b9250600383527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b8284106104e157505050810160200161048e8261049a61047e565b805460208587018101919091529093019281016104c6565b86955061049a9693506020925061048e94915060ff191682840152151560051b820101929361047e565b80fd5b600435906001600160a01b038216820361000e57565b602435906001600160a01b038216820361000e57565b503461000e57604036600319011261000e57602061057b610571610526565b6024359033611954565b6040519015158152f35b503461000e57602036600319011261000e5760206105a46004356120bd565b604051908152f35b503461000e5760408060031936011261000e576105c7610526565b602435906001600160a01b03907f000000000000000000000000429b47c4aeadd42bbcb118651c8984086bfc45518281163303610690575016907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef610669600092848452600160205285842054818101809111610683575b8585526001602052868520558354818101809111610676575b845585519081529081906020820190565b0390a35160018152602090f35b61067e61188a565b610658565b61068b61188a565b61063f565b8451636d4c6c8960e01b81529081906106ad903360048401611bcb565b0390fd5b503461000e57600036600319011261000e576007546040516001600160a01b039091168152602090f35b503461000e57600036600319011261000e576020600054604051908152f35b503461000e57602036600319011261000e5760206105a4600435611ca7565b503461000e57600036600319011261000e5760206040517f0000000000000000000000000000000000000000000000000000000064a20f808152f35b606090600319011261000e576001600160a01b0390600435828116810361000e5791602435908116810361000e579060443590565b503461000e5761079936610755565b906001600160a01b0383163381036107cc575b61049a6107ba8484876118a1565b60405190151581529081906020820190565b600090815260026020908152604080832033845290915290205460018101156107ac5791908183106108165761049a9361080c836107ba95033383611954565b50935090916107ac565b60405162461bcd60e51b815260206004820152601c60248201527f45524332303a20496e73756666696369656e7420617070726f76616c000000006044820152606490fd5b503461000e57600036600319011261000e576040517f0000000000000000000000004ea57ef203e91ae8c7d9822aa09cc719a9c01ac66001600160a01b03168152602090f35b503461000e57600036600319011261000e5760206040517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98152f35b503461000e57600036600319011261000e57602060ff60055416604051908152f35b503461000e57600036600319011261000e57467f0000000000000000000000000000000000000000000000000000000000000001036109635760207f92a2ffc3a64d5ee40b314237b14b10daa95fafa1cdb6176a6dddda6cbb9db4c2604051908152f35b602061096e466119a7565b6105a4565b503461000e57602036600319011261000e5761098d610526565b6001600160a01b03907f000000000000000000000000cd1d02fda51cd24123e857ce94e4356d5c073b3f82811633036109e55750166bffffffffffffffffffffffff60a01b6007541617600755602060405160018152f35b604051636d4c6c8960e01b81529081906106ad903360048401611bcb565b503461000e57602036600319011261000e5760206105a4600435611f1e565b503461000e57600036600319011261000e5761049a604051610a43816103ac565b60018152603160f81b6020820152604051918291826103f7565b503461000e57604036600319011261000e57600435610a7a61053c565b7f0000000000000000000000000000000000000000000000000000000064a20f809182421015610bc6576001600160801b03610b4360208095610b83947f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48916000610af960018060a01b0393610af4813033888a16612273565b611e3c565b60405162771d7560e11b81526001600160a01b03909516600486015260248501929092526001600160801b0390911660448401526000606484015291938492839182906084820190565b03927f000000000000000000000000cd1d02fda51cd24123e857ce94e4356d5c073b3f165af1908115610bb9575b600091610b8c575b50168092306118a1565b50604051908152f35b610bac9150853d8111610bb2575b610ba481836103d5565b810190611d73565b38610b79565b503d610b9a565b610bc1611b72565b610b71565b604051636d4c6c8960e01b81526015600482015242602482015260448101849052600060648201819052608482015260a490fd5b503461000e57600036600319011261000e576040517f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b03168152602090f35b503461000e57602036600319011261000e576001600160a01b03610c62610526565b1660005260016020526020604060002054604051908152f35b503461000e57602036600319011261000e576001600160a01b03610c9d610526565b1660005260066020526020604060002054604051908152f35b606090600319011261000e57600435906024356001600160a01b038116810361000e579060443590565b503461000e57610cef36610cb6565b917f0000000000000000000000000000000000000000000000000000000064a20f809081421015610eb557600754610d3d90610d31906001600160a01b031681565b6001600160a01b031690565b92610d7d610d4a83611e3c565b60405163fdb0732d60e01b81526001600160801b0390911660048201526020969095879283918891829081906024820190565b03915afa958615610ea8575b600096610e89575b507f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48956001600160801b03956001600160a01b0391610dd69088163033858c16612273565b6000610dea610de488611e3c565b94611e3c565b98610e0b6040519a8b9687958694636ba06f1b60e01b865260048601612241565b03927f000000000000000000000000cd1d02fda51cd24123e857ce94e4356d5c073b3f165af1938415610e7c575b600094610e57575b5090610e4d91306118a1565b5060405191168152f35b610e4d92919450610e7490863d8811610bb257610ba481836103d5565b939091610e41565b610e84611b72565b610e39565b610ea1919650823d8411610bb257610ba481836103d5565b9438610d91565b610eb0611b72565b610d89565b604051636d4c6c8960e01b81526015600482015242602482015260448101839052600060648201819052608482015260a490fd5b503461000e5760408060031936011261000e57610f04610526565b602435906001600160a01b03907f0000000000000000000000004ea57ef203e91ae8c7d9822aa09cc719a9c01ac682811633036106905750167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6106696000938385526001602052610f7b8187872054101561183e565b8385526001602052808686205403868620558085540385558551918291829190602083019252565b503461000e57600036600319011261000e576001600160a01b037f000000000000000000000000cd1d02fda51cd24123e857ce94e4356d5c073b3f81811633036109e5576110168161101c937f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4816611bf9565b30611bf9565b602060405160018152f35b503461000e57604036600319011261000e5760043561104461053c565b907f0000000000000000000000000000000000000000000000000000000064a20f809081421015610eb557600754610e0b92919061108c90610d31906001600160a01b031681565b936110ca61109983611e3c565b60405163fdb0732d60e01b81526001600160801b039091166004820152602096879283918391829081906024820190565b03915afa90811561116a575b60009161114d575b506001600160801b03947f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48916001600160a01b0391906111249088163033858716612273565b600061112f87611e3c565b604051636ba06f1b60e01b8152998a95869485939160048501612213565b6111649150823d8411610bb257610ba481836103d5565b386110de565b611172611b72565b6110d6565b503461000e5760008060031936011261052357604051908060045461119b8161035b565b808552916001918083169081156104f957506001146111c45761049a8561048e818703826103d5565b9250600483527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b82841061120757505050810160200161048e8261049a61047e565b805460208587018101919091529093019281016111ec565b503461000e5761122e36610755565b7f0000000000000000000000004ea57ef203e91ae8c7d9822aa09cc719a9c01ac6929091906001600160a01b0390818516330361129c5761129093945016600052600260205260406000209060018060a01b0316600052602052604060002090565b55602060405160018152f35b604051636d4c6c8960e01b8152806106ad873360048401611bcb565b608090600319011261000e57600435906001600160a01b0390602435828116810361000e5791604435908116810361000e579060643590565b503461000e5760206105a4611305366112b8565b92919091612b69565b503461000e5760206105a4611322366112b8565b92919091612768565b503461000e57604036600319011261000e57602061057b61134a610526565b60243590336118a1565b503461000e57600036600319011261000e576040517f000000000000000000000000cd1d02fda51cd24123e857ce94e4356d5c073b3f6001600160a01b03168152602090f35b503461000e57602036600319011261000e5760206105a4600435611e50565b606090600319011261000e57600435906001600160a01b0390602435828116810361000e5791604435908116810361000e5790565b503461000e5760206105a4611402366113b9565b9161233b565b503461000e5760206105a461141c366113b9565b916129c5565b503461000e5761143136610cb6565b7f0000000000000000000000000000000000000000000000000000000064a20f8092834210156114cc5760209384610b83936001600160801b03937f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb489360006114ac610de460018060a01b0394610af4813033898d16612273565b95610b436040519788968795869462771d7560e11b865260048601612241565b604051636d4c6c8960e01b81526015600482015242602482015260448101859052600060648201819052608482015260a490fd5b503461000e57600036600319011261000e576040517f000000000000000000000000429b47c4aeadd42bbcb118651c8984086bfc45516001600160a01b03168152602090f35b503461000e57602036600319011261000e5760206105a4600435611cdd565b503461000e57600036600319011261000e5760206040517f00000000000000000000000000000000000000000000000000000000000000018152f35b503461000e57602036600319011261000e5760206105a46115c0610526565b611d10565b503461000e5760e036600319011261000e576115df610526565b6115e761053c565b604435906064359260843560ff8116810361000e5760006020916116a761173161173d61179c9961161a42821015611b0a565b6001600160a01b03881660009081526006602052604090209081549161163f83611b56565b9055604080517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98a82019081526001600160a01b03808d1660208301528d1692810192909252606082018d9052608082019390935260a08101919091529093849060c0830190565b03936116bb601f19958681018352826103d5565b519020927f0000000000000000000000000000000000000000000000000000000000000001461486146117b7577f92a2ffc3a64d5ee40b314237b14b10daa95fafa1cdb6176a6dddda6cbb9db4c2935b6040519384918983019687909160429261190160f01b8352600283015260228201520190565b039081018352826103d5565b5190206040805191825260ff92909216602082015260a4359181019190915260c435606082015281805260809060015afa156117aa575b600051611797906001600160a01b03908116801515918261179e575b5050611b7f565b611954565b005b84161490503880611790565b6117b2611b72565b611774565b6117c0466119a7565b9361170b565b503461000e57604036600319011261000e5760206118166117e5610526565b6117ed61053c565b6001600160a01b0391821660009081526002855260408082209290931681526020919091522090565b54604051908152f35b503461000e57602036600319011261000e5760206105a4600435611d92565b1561184557565b60405162461bcd60e51b815260206004820152601b60248201527f45524332303a20496e73756666696369656e742062616c616e636500000000006044820152606490fd5b50634e487b7160e01b600052601160045260246000fd5b60207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9160018060a01b038091169384600052600183526118e986604060002054101561183e565b60008581526001808552604080832080548a900390556001600160a01b0384168352602091909152902054868101809111611947575b6001600160a01b03821660009081526001602052604090205b556040519586521693a3600190565b61194f61188a565b61191f565b6001600160a01b0390811660008181526002602090815260408083208686168452825290912091937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259391928690611938565b604051600354600092916119ba8261035b565b9384825260209485830193600190878282169182600014611acd575050600114611a6a575b5050906119f281611a64949303826103d5565b51902092611a56611a01611aed565b805190830120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f948101948552602085019790975283015260608201939093523060808201529291829060a0850190565b03601f1981018352826103d5565b51902090565b86919493925060036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b946000915b818310611ab65750939450919250908201016119f2826119df565b865485840185015295860195889390920191611a9b565b60ff1916875292151560051b850190920192506119f291508390506119df565b60405190611afa826103ac565b60018252603160f81b6020830152565b15611b1157565b60405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606490fd5b6001906000198114611b66570190565b611b6e61188a565b0190565b506040513d6000823e3d90fd5b15611b8657565b60405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606490fd5b60008082526020820181905260408201526001600160a01b0391821660608201529116608082015260a00190565b60405163095ea7b360e01b81526001600160a01b0390921660048301526000196024830152611c3391600091829160449183905af1611c70565b15611c3a57565b60405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b6044820152606490fd5b6000903d9015611ca0579081602014611c93575015611c8e57600090565b600190565b9050602081803e51151590565b908181803efd5b7f0000000000000000000000000000000000000000000000000000000064a20f804210611cd15790565b611cda90611f1e565b90565b7f0000000000000000000000000000000000000000000000000000000064a20f804210611d075790565b611cda906120bd565b7f0000000000000000000000000000000000000000000000000000000064a20f804210611d52576001600160a01b031660009081526001602052604090205490565b6001600160a01b0316600090815260016020526040902054611cda90611f1e565b9081602091031261000e57516001600160801b038116810361000e5790565b7f0000000000000000000000000000000000000000000000000000000064a20f804210611dbf5750600090565b6007546001600160a01b031690602490602090611ddb90611e3c565b92604051928380926304f9ef2360e21b82526001600160801b0380971660048301525afa908115611e2f575b600091611e1357501690565b611e2b915060203d8111610bb257610ba481836103d5565b1690565b611e37611b72565b611e07565b6001600160801b039081811161000e571690565b7f0000000000000000000000000000000000000000000000000000000064a20f804210611e7d5750600090565b6007546001600160a01b031690602490602090611e9990611e3c565b926040519283809263fdb0732d60e01b82526001600160801b0380971660048301525afa908115611e2f57600091611e1357501690565b9081602091031261000e575190565b8060001904821181151516611ef2570290565b611efa61188a565b0290565b8115611f08570490565b634e487b7160e01b600052601260045260246000fd5b7f0000000000000000000000000000000000000000000000000000000064a20f8080421015611fb95750611fa260206001600160801b0392611f76611f70610d31610d3160075460018060a01b031690565b91611e3c565b6040516327bab06360e01b81526001600160801b03909116600482015292839190829081906024820190565b03915afa908115611e2f57600091611e1357501690565b6040516391b46a9160e01b81526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb481660048201526024810191909152611cda9161207091610af4919061206a9061205e90602081806044810103817f0000000000000000000000004ea57ef203e91ae8c7d9822aa09cc719a9c01ac66001600160a01b03165afa9081156120b0575b600091612082575b50611e3c565b6001600160801b031690565b90611edf565b6001600160801b036000549116611efe565b6120a3915060203d81116120a9575b61209b81836103d5565b810190611ed0565b38612058565b503d612091565b6120b8611b72565b612050565b7f0000000000000000000000000000000000000000000000000000000064a20f808042101561213b5750611fa260206001600160801b039261210f611f70610d31610d3160075460018060a01b031690565b60405163b0f2892160e01b81526001600160801b03909116600482015292839190829081906024820190565b6121a2906020612151611cda9460005490611edf565b6040516391b46a9160e01b81526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4816600482015260248101939093529192839081906044820190565b03817f0000000000000000000000004ea57ef203e91ae8c7d9822aa09cc719a9c01ac66001600160a01b03165afa918215612206575b6000926121e6575b50611efe565b6121ff91925060203d81116120a95761209b81836103d5565b90386121e0565b61220e611b72565b6121d8565b606091949392608082019560018060a01b0316825260208201526001600160801b0380931660408201520152565b6001600160a01b03909116815260208101919091526001600160801b0391821660408201529116606082015260800190565b600092836064926122af968295604051946323b872dd60e01b865260018060a01b03809216600487015216602485015260448401525af1611c70565b156122b657565b60405162461bcd60e51b81526020600482015260146024820152731d1c985b9cd9995c88199c9bdb4819985a5b195960621b6044820152606490fd5b919082039182116122ff57565b61230761188a565b565b6001600160a01b0391821681526020810192909252918216604082015291166060820152608081019190915260a00190565b90612345826120bd565b7f0000000000000000000000000000000000000000000000000000000064a20f80938442106000146125cd5761237c8230836118a1565b506001600160a01b0391818316330361245e575050916123ea916001600160801b03949360207f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48956123cd85611e3c565b604051637ef1c17560e11b81529687928392908a60048501612213565b03816000857f000000000000000000000000cd1d02fda51cd24123e857ce94e4356d5c073b3f165af1938415612451575b60009461242f575b50611e2b939416612954565b611e2b945061244b9060203d8111610bb257610ba481836103d5565b93612423565b612459611b72565b61241b565b6001600160a01b03821660009081526002602052604090209295926124979033905b9060018060a01b0316600052602052604060002090565b5481811061259757611cda9594936001600160801b03936124e06124c0612528956020956122f2565b6001600160a01b0390921660009081526002602052604090203390612480565b5561250b7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4896611e3c565b604051637ef1c17560e11b81529384928392908960048501612213565b038160008a7f000000000000000000000000cd1d02fda51cd24123e857ce94e4356d5c073b3f165af190811561258a575b60009161256c575b501693849216612954565b612584915060203d8111610bb257610ba481836103d5565b38612561565b612592611b72565b612559565b604051636d4c6c8960e01b815260146004820152602481019190915260448101869052600060648201819052608482015260a490fd5b6001600160a01b039594919350858116330361268e5750936020929160006126309596604051968795869485936370a03ced60e01b855233907f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4860048701612309565b03927f0000000000000000000000004ea57ef203e91ae8c7d9822aa09cc719a9c01ac6165af1908115612681575b600091612669575090565b611cda915060203d81116120a95761209b81836103d5565b612689611b72565b61265e565b6001600160a01b03811660009081526002602052604090209195916126b4903390612480565b54848110612732578495966126cd6020966000936122f2565b6001600160a01b03841660009081526002602052604090206126f0903390612480565b55612630604051978896879586946370a03ced60e01b86527f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4860048701612309565b604051636d4c6c8960e01b815260146004820152602481019190915260448101859052600060648201819052608482015260a490fd5b92919092612775816120bd565b937f0000000000000000000000000000000000000000000000000000000064a20f80928342106000146128ee576127ad8630836118a1565b506001600160a01b0395818716330361281b5750506001600160801b039460207f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48956127fb611f7086611e3c565b956123ea6040519788938493637ef1c17560e11b85528b60048601612241565b6001600160a01b03821660009081526002602052604090209395929493612843903390612480565b548181106128b85792611cda9695949261286a6124c06020946001600160801b03976122f2565b55612898611f707f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4897611e3c565b926125286040519485938493637ef1c17560e11b85528a60048601612241565b604051636d4c6c8960e01b815260146004820152602481019190915260448101879052600060648201819052608482015260a490fd5b6001600160a01b039695945090929150858116330361268e5750936020929160006126309596604051968795869485936370a03ced60e01b855233907f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4860048701612309565b6044600092838093612987966040519363a9059cbb60e01b855260018060a01b0316600485015260248401525af1611c70565b1561298e57565b60405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b907f0000000000000000000000000000000000000000000000000000000064a20f80804210600014612b09576129fc8330866118a1565b506001600160a01b03938085163303612a925750906001600160801b036125286020611cda9594612a4d7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4896611e3c565b60405163d744e26960e01b81526001600160a01b038816600482015260248101929092526001600160801b031660448201526000606482015291829081906084820190565b6001600160a01b0381166000908152600260205260409020612ab5903390612480565b548481106127325760208594936001600160801b0393612ade6124c0611cda99612528966122f2565b55612a4d7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4896611e3c565b6001600160a01b039493858116330361268e5750936020929160006126309596604051968795869485936370a03ced60e01b855233907f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4860048701612309565b91927f0000000000000000000000000000000000000000000000000000000064a20f8090814210600014612c8c57612ba28430876118a1565b506001600160a01b03948086163303612c145750611cda93929160206001600160801b0392612bf4611f707f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4897611e3c565b92612528604051948593849363d744e26960e01b85528a60048601612241565b6001600160a01b0381166000908152600260205260409020612c37903390612480565b54858110612597576001600160801b039286959492612c5e6124c0611cda996020956122f2565b55612bf4611f707f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4897611e3c565b506001600160a01b039493858116330361268e5750936020929160006126309596604051968795869485936370a03ced60e01b855233907f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486004870161230956fea26469706673582212208530e193d9391de7f27e9397e62718fc6cde8627999f6fa7228b7435e6f7b91564736f6c63430008100033
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.