More Info
Private Name Tags
ContractCreator
Latest 6 from a total of 6 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Yodl With Token | 20675767 | 121 days ago | IN | 0 ETH | 0.00013044 | ||||
Transfer Fee | 20669042 | 122 days ago | IN | 0 ETH | 0.00188419 | ||||
Yodl With Uniswa... | 20633072 | 127 days ago | IN | 0.0019687 ETH | 0.00027632 | ||||
Yodl With Token | 20618421 | 129 days ago | IN | 0 ETH | 0.00005518 | ||||
Yodl With Uniswa... | 20590543 | 133 days ago | IN | 0.00187743 ETH | 0.00021523 | ||||
Yodl With Uniswa... | 20590525 | 133 days ago | IN | 0.00187743 ETH | 0.0002865 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
YodlRouter
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BSL-1.1 // @author samthebuilder.eth pragma solidity ^0.8.26; import "../routers/YodlTransferRouter.sol"; import "../routers/YodlCurveRouter.sol"; import "../routers/YodlUniswapRouter.sol"; contract YodlRouter is YodlTransferRouter, YodlCurveRouter, YodlUniswapRouter { constructor() AbstractYodlRouter() YodlTransferRouter() YodlCurveRouter(0x99a58482BD75cbab83b27EC03CA68fF489b5788f) YodlUniswapRouter(0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45) { version = "vSam"; yodlFeeBps = 20; yodlFeeTreasury = 0x9C48d180e4eEE0dA2A899EE1E4c533cA5e92db77; wrappedNativeToken = IWETH9(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); } }
// SPDX-License-Identifier: BSL-1.1 // @author samthebuilder.eth pragma solidity ^0.8.26; import "../AbstractYodlRouter.sol"; import "../interfaces/IBeforeHook.sol"; abstract contract YodlTransferRouter is AbstractYodlRouter { struct YodlTransferParams { // The message attached to the payment. If present, the router will take a fee. bytes32 memo; // The amount to pay before any price feeds are applied. This amount will be converted by the price feeds and then the sender will pay the converted amount in the given token. uint256 amount; // Array of Chainlink price feeds. See `exchangeRate` method for more details. PriceFeed[2] priceFeeds; // Token address to be used for the payment. Either an ERC20 token or the native token address. address token; // Address to receive the payment address receiver; // Address to receive an extra fee that is taken from the payment amount address extraFeeReceiver; // Size of the extra fee in terms of basis points (or 0 for none) uint256 extraFeeBps; // Metadata tracker for the payment uint256 yd; // List of YApps that are allowed to be called with IBeforeHook.beforeHook extension YApp[] yAppList; } /** * @notice Handles payments when sending tokens directly without DEX. * ## Example: Pay without pricefeeds, e.g. USDC transfer * * yodlWithToken( * "tx-123", // memo * 5*10**18, // 5$ * [0x0, 0x0], // no pricefeeds * 0xUSDC, // usdc token address * 0xAlice // receiver token address * ) * * ## Example: Pay with pricefeeds (EUR / USD) * * The user entered the amount in EUR, which gets converted into * USD by the on-chain pricefeed. * * yodlWithToken( * "tx-123", // memo * 4.5*10**18, // 4.5 EUR (~5$). * [0xEURUSD, 0x0], // EUR/USD price feed * 0xUSDC, // usdc token address * 0xAlice // receiver token address * ) * * * ## Example: Pay with extra fee * * 3rd parties can receive an extra fee that is taken directly from * the receivable amount. * * yodlWithToken( * "tx-123", // memo * 4.5*10**18, // 4.5 EUR (~5$). * [0xEURUSD, 0x0], // * 0xUSDC, // usdc token address * 0xAlice, // receiver token address * 0x3rdParty // extra fee for 3rd party provider * 50, // extra fee bps 0.5% * ) * @dev This is the most gas efficient payment method. It supports currency conversion using price feeds. The * native token (ETH, AVAX, MATIC) is represented by the NATIVE_TOKEN constant. * @param params Struct that contains all the relevant parameters. See `YodlNativeParams` for more details. * @return Amount received by the receiver */ function yodlWithToken(YodlTransferParams calldata params) external payable returns (uint256) { require(params.amount != 0, "invalid amount"); uint256 finalAmount = params.amount; // transform amount with priceFeeds if ( params.priceFeeds[0].feedType != NULL_FEED || params.priceFeeds[1].feedType != NULL_FEED ) { { int256[2] memory prices; address[2] memory priceFeedsUsed; (finalAmount, priceFeedsUsed, prices) = exchangeRate(params.priceFeeds, params.amount); emitConversionEvent(params.priceFeeds, prices); } } if (params.token != NATIVE_TOKEN) { // ERC20 token require(IERC20(params.token).allowance(msg.sender, address(this)) >= finalAmount, "insufficient allowance"); } else { // Native ether require(msg.value >= finalAmount, "insufficient gas provided"); } uint256 totalFee = 0; if (params.memo != "") { totalFee += calculateFee(finalAmount, yodlFeeBps); } if (params.extraFeeReceiver != address(0)) { // 50% maximum extra fee require(params.extraFeeBps < MAX_EXTRA_FEE_BPS, "extraFeeBps too high"); totalFee += transferFee( finalAmount, params.extraFeeBps, params.token, params.token == NATIVE_TOKEN ? address(this) : msg.sender, params.extraFeeReceiver ); } uint256 receivedAmount = finalAmount - totalFee; if (params.yAppList.length > 0) { for (uint256 i = 0; i < params.yAppList.length; i++) { IBeforeHook(params.yAppList[i].yApp).beforeHook( msg.sender, params.receiver, receivedAmount, params.token, params.yAppList[i].sessionId, params.yAppList[i].payload ); } } // Transfer to receiver if (params.token != NATIVE_TOKEN) { // ERC20 token TransferHelper.safeTransferFrom(params.token, msg.sender, params.receiver, receivedAmount); } else { // Native ether (bool success,) = params.receiver.call{value: receivedAmount}(""); require(success, "transfer of the native token to the recipient failed"); emit YodlNativeTokenTransfer(msg.sender, params.receiver, receivedAmount); } emit Yodl(msg.sender, params.receiver, params.token, finalAmount, totalFee, params.memo); return receivedAmount; } }
// SPDX-License-Identifier: BSL-1.1 // @author samthebuilder.eth pragma solidity ^0.8.26; import "../interfaces/ICurveRouter.sol"; import "../AbstractYodlRouter.sol"; import "../interfaces/IBeforeHook.sol"; abstract contract YodlCurveRouter is AbstractYodlRouter { ICurveRouter private curveRouter; /// @notice Parameters for a payment through Curve /// @dev The`route`, `swapParams` and `factoryAddresses` should be determined client-side by the CurveJS client. struct YodlCurveParams { address sender; address receiver; uint256 amountIn; // amount of tokenIn needed to satisfy amountOut // The exact amount expected by merchant in tokenOut // If we are using price feeds, this is in terms of the invoice amount, but it must have the same decimals as tokenOut uint256 amountOut; bytes32 memo; address[9] route; uint256[3][4] swapParams; // [i, j, swap_type] where i and j are the coin index for the n'th pool in route address[4] factoryAddresses; PriceFeed[2] priceFeeds; address extraFeeReceiver; uint256 extraFeeBps; uint256 yd; // List of YApps that are allowed to be called with IBeforeHook.beforeHook extension YApp[] yAppList; } constructor(address _curveRouter) { curveRouter = ICurveRouter(_curveRouter); } /// @notice Handles a payment with a swap through Curve /// @dev This needs to have a valid Curve router or it will revert. Excess tokens from the swap as a result /// of slippage are in terms of the token out. /// @param params Struct that contains all the relevant parameters. See `YodlCurveParams` for more details. /// @return The amount received in terms of token out by the Curve swap function yodlWithCurve(YodlCurveParams calldata params) external payable returns (uint256) { require(address(curveRouter) != address(0), "curve router not present"); (address tokenOut, address tokenIn) = decodeTokenOutTokenInCurve(params.route); // This is how much the recipient needs to receive uint256 amountOutExpected; if ( params.priceFeeds[0].feedType != NULL_FEED || params.priceFeeds[1].feedType != NULL_FEED ) { // Convert amountOut from invoice currency to swap currency using price feed int256[2] memory prices; address[2] memory priceFeeds; (amountOutExpected, priceFeeds, prices) = exchangeRate(params.priceFeeds, params.amountOut); emitConversionEvent(params.priceFeeds, prices); } else { amountOutExpected = params.amountOut; } if (params.yAppList.length > 0) { for (uint256 i = 0; i < params.yAppList.length; i++) { IBeforeHook(params.yAppList[i].yApp).beforeHook( msg.sender, params.receiver, amountOutExpected, tokenOut, params.yAppList[i].sessionId, params.yAppList[i].payload ); } } // There should be no other situation in which we send a transaction with native token if (msg.value != 0) { // Wrap the native token require(msg.value >= params.amountIn, "insufficient gas provided"); wrappedNativeToken.deposit{value: params.amountIn}(); // Update the tokenIn to wrapped native token // wrapped native token has the same number of decimals as native token // wrapped native token is already the first token in the route parameter tokenIn = address(wrappedNativeToken); } else { // Transfer the ERC20 token from the sender to the YodlRouter TransferHelper.safeTransferFrom(tokenIn, msg.sender, address(this), params.amountIn); } TransferHelper.safeApprove(tokenIn, address(curveRouter), params.amountIn); // Make the swap - the YodlRouter will receive the tokens uint256 amountOut = curveRouter.exchange_multiple( params.route, params.swapParams, params.amountIn, amountOutExpected, // this will revert if we do not get at least this amount params.factoryAddresses, // this is for zap contracts address(this) // the Yodl router will receive the tokens ); require(amountOut >= amountOutExpected, "amountOut is less then amountOutExpected"); // Handle fees for the transaction - in terms out the token out uint256 totalFee = 0; if (params.memo != "") { totalFee += calculateFee(amountOutExpected, yodlFeeBps); } // Handle extra fees if (params.extraFeeReceiver != address(0)) { // 50% maximum extra fee require(params.extraFeeBps < MAX_EXTRA_FEE_BPS, "extraFeeBps too high"); totalFee += transferFee(amountOutExpected, params.extraFeeBps, tokenOut, address(this), params.extraFeeReceiver); } if (tokenOut == NATIVE_TOKEN) { // Handle unwrapping wrapped native token uint256 balance = IWETH9(wrappedNativeToken).balanceOf(address(this)); // Unwrap and use NATIVE_TOKEN address as tokenOut require(balance >= amountOutExpected, "Wrapped balance is less then amountOutExpected"); IWETH9(wrappedNativeToken).withdraw(balance); // Need to transfer native token to receiver (bool success,) = params.receiver.call{value: amountOutExpected - totalFee}(""); require(success, "transfer of native to receiver failed"); emit YodlNativeTokenTransfer(params.sender, params.receiver, amountOutExpected - totalFee); } else { // Transfer tokens to receiver TransferHelper.safeTransfer(tokenOut, params.receiver, amountOutExpected - totalFee); } emit Yodl(params.sender, params.receiver, tokenOut, amountOutExpected, totalFee, params.memo); return amountOut; } /// @notice Helper method to determine the token in and out from a Curve route /// @param route Route for a Curve swap in the form of [token, pool address, token...] with zero addresses once the /// swap has completed /// @return The tokenOut and tokenIn function decodeTokenOutTokenInCurve(address[9] memory route) internal pure returns (address, address) { address tokenIn = route[0]; address tokenOut = route[2]; // Output tokens can be located at indices 2, 4, 6 or 8, if the loop finds nothing, then it is index 2 for (uint256 i = 4; i >= 2; i--) { if (route[i * 2] != address(0)) { tokenOut = route[i * 2]; break; } } require(tokenOut != address(0), "Invalid route parameter"); return (tokenOut, tokenIn); } }
// SPDX-License-Identifier: BSL-1.1 // @author samthebuilder.eth pragma solidity ^0.8.26; import "../AbstractYodlRouter.sol"; import "../../lib/swap-router-contracts/contracts/interfaces/ISwapRouter02.sol"; import "../interfaces/IBeforeHook.sol"; abstract contract YodlUniswapRouter is AbstractYodlRouter { ISwapRouter02 public uniswapRouter; enum SwapType { SINGLE, MULTI } /// @notice Parameters for a payment through Uniswap struct YodlUniswapParams { address sender; address receiver; uint256 amountIn; // amount of tokenIn needed to satisfy amountOut uint256 amountOut; // The exact amount expected by merchant in tokenOut bytes32 memo; bytes path; // (address: tokenOut, uint24 poolfee, address: tokenIn) OR (address: tokenOut, uint24 poolfee2, address: tokenBase, uint24 poolfee1, tokenIn) PriceFeed[2] priceFeeds; address extraFeeReceiver; uint256 extraFeeBps; SwapType swapType; uint256 yd; // List of YApps that are allowed to be called with IBeforeHook.beforeHook extension YApp[] yAppList; } constructor(address _uniswapRouter) { uniswapRouter = ISwapRouter02(_uniswapRouter); } /// @notice Handles a payment with a swap through Uniswap /// @dev This needs to have a valid Uniswap router or it will revert. Excess tokens from the swap as a result /// of slippage are in terms of the token in. /// @param params Struct that contains all the relevant parameters. See `YodlUniswapParams` for more details. /// @return The amount spent in terms of token in by Uniswap to complete this payment function yodlWithUniswap(YodlUniswapParams calldata params) external payable returns (uint256) { require(address(uniswapRouter) != address(0), "uniswap router not present"); (address tokenOut, address tokenIn) = decodeTokenOutTokenInUniswap(params.path, params.swapType); uint256 amountSpent; // This is how much the recipient needs to receive uint256 amountOutExpected; if ( params.priceFeeds[0].feedType != NULL_FEED || params.priceFeeds[1].feedType != NULL_FEED ) { // Convert amountOut from invoice currency to swap currency using price feed int256[2] memory prices; address[2] memory priceFeeds; (amountOutExpected, priceFeeds, prices) = exchangeRate(params.priceFeeds, params.amountOut); emitConversionEvent(params.priceFeeds, prices); } else { amountOutExpected = params.amountOut; } if (params.yAppList.length > 0) { for (uint256 i = 0; i < params.yAppList.length; i++) { IBeforeHook(params.yAppList[i].yApp).beforeHook( tx.origin, params.receiver, amountOutExpected, tokenOut, params.yAppList[i].sessionId, params.yAppList[i].payload ); } } // There should be no other situation in which we send a transaction with native token if (msg.value != 0) { // Wrap the native token require(msg.value >= params.amountIn, "insufficient gas provided"); wrappedNativeToken.deposit{value: params.amountIn}(); // Update the tokenIn to wrapped native token tokenIn = address(wrappedNativeToken); } else { // Transfer the ERC20 token from the sender to the YodlRouter TransferHelper.safeTransferFrom(tokenIn, tx.origin, address(this), params.amountIn); } TransferHelper.safeApprove(tokenIn, address(uniswapRouter), params.amountIn); // Special case for when we want native token out bool useNativeToken = false; if (tokenOut == NATIVE_TOKEN) { useNativeToken = true; tokenOut = address(wrappedNativeToken); } if (params.swapType == SwapType.SINGLE) { IV3SwapRouter.ExactOutputSingleParams memory routerParams = IV3SwapRouter.ExactOutputSingleParams({ tokenIn: tokenIn, tokenOut: tokenOut, fee: decodeSinglePoolFee(params.path), recipient: address(this), amountOut: amountOutExpected, amountInMaximum: params.amountIn, sqrtPriceLimitX96: 0 }); amountSpent = uniswapRouter.exactOutputSingle(routerParams); } else { // We need to extract the path details so that we can use the tokenIn value from earlier which may have been replaced by WETH (, uint24 poolFee2, address tokenBase, uint24 poolFee1,) = abi.decode(params.path, (address, uint24, address, uint24, address)); IV3SwapRouter.ExactOutputParams memory routerParams = IV3SwapRouter.ExactOutputParams({ path: abi.encodePacked(tokenOut, poolFee2, tokenBase, poolFee1, tokenIn), recipient: address(this), amountOut: amountOutExpected, amountInMaximum: params.amountIn }); amountSpent = uniswapRouter.exactOutput(routerParams); } // Handle unwrapping wrapped native token if (useNativeToken) { // Unwrap and use NATIVE_TOKEN address as tokenOut IWETH9(wrappedNativeToken).withdraw(amountOutExpected); tokenOut = NATIVE_TOKEN; } // Calculate fee from amount out uint256 totalFee = 0; if (params.memo != "") { totalFee += calculateFee(amountOutExpected, yodlFeeBps); } // Handle extra fees if (params.extraFeeReceiver != address(0)) { // 50% maximum extra fee require(params.extraFeeBps < MAX_EXTRA_FEE_BPS, "extraFeeBps too high"); totalFee += transferFee(amountOutExpected, params.extraFeeBps, tokenOut, address(this), params.extraFeeReceiver); } if (tokenOut == NATIVE_TOKEN) { (bool success,) = params.receiver.call{value: amountOutExpected - totalFee}(""); require(success, "transfer failed"); emit YodlNativeTokenTransfer(params.sender, params.receiver, amountOutExpected - totalFee); } else { // transfer tokens to receiver TransferHelper.safeTransfer(tokenOut, params.receiver, amountOutExpected - totalFee); } emit Yodl(params.sender, params.receiver, tokenOut, amountOutExpected, totalFee, params.memo); TransferHelper.safeApprove(tokenIn, address(uniswapRouter), 0); return amountSpent; } /// @notice Helper method to determine the token in and out from a Uniswap path /// @param path The path for a Uniswap swap /// @param swapType Enum for whether the swap is a single hop or multiple hop /// @return The tokenOut and tokenIn function decodeTokenOutTokenInUniswap(bytes memory path, SwapType swapType) internal pure returns (address, address) { address tokenOut; address tokenIn; if (swapType == SwapType.SINGLE) { (tokenOut,, tokenIn) = abi.decode(path, (address, uint24, address)); } else { (tokenOut,,,, tokenIn) = abi.decode(path, (address, uint24, address, uint24, address)); } return (tokenOut, tokenIn); } /// @notice Helper method to get the fee for a single hop swap for Uniswap /// @param path The path for a Uniswap swap /// @return The pool fee for given swap path function decodeSinglePoolFee(bytes memory path) internal pure returns (uint24) { (, uint24 poolFee,) = abi.decode(path, (address, uint24, address)); return poolFee; } }
// SPDX-License-Identifier: BSL-1.1 pragma solidity ^0.8.26; import "../lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol"; import "../lib/v3-periphery/contracts/interfaces/external/IWETH9.sol"; import "../lib/v3-periphery/contracts/libraries/TransferHelper.sol"; import "../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; abstract contract AbstractYodlRouter { string public version; address public yodlFeeTreasury; uint256 public yodlFeeBps; IWETH9 public wrappedNativeToken; address public constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; uint256 public constant MAX_EXTRA_FEE_BPS = 5_000; // 50% address public constant RATE_VERIFIER = 0xc71f6e1e4665d319610afA526BE529202cA13bB7; int8 public constant NULL_FEED = 0; int8 public constant CHAINLINK_FEED = 1; int8 public constant EXTERNAL_FEED = 2; /// @notice Emitted when a payment goes through /// @param sender The address who has made the payment /// @param receiver The address who has received the payment /// @param token The address of the token that was used for the payment. Either an ERC20 token or the native token /// address. /// @param amount The amount paid by the sender in terms of the token /// @param fees The fees taken by the Yodl router from the amount paid /// @param memo The message attached to the payment event Yodl( address indexed sender, address indexed receiver, address token, uint256 amount, uint256 fees, bytes32 memo ); /// @notice Emitted when a native token transfer occurs /// @param sender The address who has made the payment /// @param receiver The address who has received the payment /// @param amount The amount paid by the sender in terms of the native token event YodlNativeTokenTransfer( address indexed sender, address indexed receiver, uint256 indexed amount ); /// @notice Emitted when a conversion has occurred from one currency to another using a Chainlink price feed /// @param priceFeed0 The address of the price feed used for conversion /// @param priceFeed1 The address of the price feed used for conversion /// @param exchangeRate0 The rate used from the price feed at the time of conversion /// @param exchangeRate1 The rate used from the price feed at the time of conversion event Convert( address indexed priceFeed0, address indexed priceFeed1, int256 exchangeRate0, int256 exchangeRate1 ); /// @notice Emitted when a conversion has occurred from one currency to another using a Chainlink price feed and external rate /// @param currency0 The currency used for the first conversion /// @param priceFeed1 The address of the price feed used for conversion /// @param exchangeRate0 The rate used from the price feed at the time of conversion /// @param exchangeRate1 The rate used from the price feed at the time of conversion event ConvertWithExternalRate( string indexed currency0, address indexed priceFeed1, int256 exchangeRate0, int256 exchangeRate1 ); /** * @notice Struct to hold the YApp address and the YD ID * @param yApp The address of the YApp * @param yd The ID of the YD * @param payload The payload to be sent to the YApp */ struct YApp { address yApp; uint256 sessionId; bytes[] payload; } /** * @notice Struct to hold the price feed information, it's either Chainlink or external * @param feedAddress The address of the Chainlink price feed, ZERO otherwise * @param feedType The type of the price feed, 1 for Chainlink, 2 for external * @param currency The currency of the price feed, if external, ZERO otherwise * @param amount The amount to be converted by the price feed exchange rates, if external, ZERO otherwise * @param decimals The number of decimals in the price feed, if external, ZERO otherwise * @param signature The signature of the price feed, if external, ZERO otherwise */ struct PriceFeed { address feedAddress; int8 feedType; string currency; uint256 amount; uint256 deadline; bytes signature; } /// @notice Enables the contract to receive Ether /// @dev We need a receive method for when we withdraw WETH to the router. It does not need to do anything. receive() external payable {} /** * @notice Calculates exchange rates from a given price feed * @dev At most we can have 2 price feeds. * * We will use a zero address to determine if we need to inverse a singular price feeds. * * For multiple price feeds, we will always pass them in such that we multiply by the first and divide by the second. * This works because all of our price feeds have USD as the quote currency. * * a) CHF_USD/_______ => 85 CHF invoiced, 100 USD sent * b) _______/CHF_USD => 100 USD invoiced, 85 CHF sent * c) ETH_USD/CHF_USD => ETH invoiced, CHF sent * * The second pricefeed is inversed. So in b) and c) `CHF_USD` turns into `USD_CHF`. * * @param priceFeeds Array of PriceFeeds, either Chainlink or external * @param amount Amount to be converted by the price feed exchange rates * @return converted The amount after conversion * @return priceFeedsUsed The price feeds in the order they were used * @return prices The exchange rates from the price feeds */ function exchangeRate( PriceFeed[2] calldata priceFeeds, uint256 amount ) public view returns ( uint256 converted, address[2] memory priceFeedsUsed, int256[2] memory prices ) { bool shouldInverse; AggregatorV3Interface priceFeedOne; AggregatorV3Interface priceFeedTwo; // might not exist if (priceFeeds[0].feedType == NULL_FEED) { // Inverse the price feed. invoiceCurrency: USD, settlementCurrency: CHF if (priceFeeds[1].feedType == NULL_FEED) { return ( amount, [address(0), address(0)], [int256(1), int256(1)] ); } else { shouldInverse = true; priceFeedOne = AggregatorV3Interface(priceFeeds[1].feedAddress); } } else { // No need to inverse. invoiceCurrency: CHF, settlementCurrency: USD if (priceFeeds[0].feedType == EXTERNAL_FEED) { if (!verifyRateSignature(priceFeeds[0])) { revert("Invalid signature for external price feed"); } } else { priceFeedOne = AggregatorV3Interface(priceFeeds[0].feedAddress); } if (priceFeeds[1].feedAddress != address(0)) { // Multiply by the first, divide by the second // Will always be A -> USD -> B priceFeedTwo = AggregatorV3Interface(priceFeeds[1].feedAddress); } } uint256 decimals; int256 price; if (priceFeeds[0].feedType == EXTERNAL_FEED) { decimals = uint256(10 ** uint256(18)); price = int256(priceFeeds[0].amount); prices[0] = price; } else { // Calculate the converted value using price feeds decimals = uint256(10 ** uint256(priceFeedOne.decimals())); (, price, , , ) = priceFeedOne.latestRoundData(); prices[0] = price; } if (shouldInverse) { converted = (amount * decimals) / uint256(price); } else { converted = (amount * uint256(price)) / decimals; } // We will always divide by the second price feed if (address(priceFeedTwo) != address(0)) { decimals = uint256(10 ** uint256(priceFeedTwo.decimals())); (, price, , , ) = priceFeedTwo.latestRoundData(); prices[1] = price; converted = (converted * decimals) / uint256(price); } return ( converted, [priceFeeds[0].feedAddress, priceFeeds[1].feedAddress], prices ); } function emitConversionEvent( PriceFeed[2] memory priceFeeds, int256[2] memory prices ) public { if (priceFeeds[0].feedType == EXTERNAL_FEED) { emit ConvertWithExternalRate( priceFeeds[0].currency, priceFeeds[1].feedAddress, prices[0], prices[1] ); } else { emit Convert( priceFeeds[0].feedAddress, priceFeeds[1].feedAddress, prices[0], prices[1] ); } } /// @notice Helper function to calculate fees /// @dev A basis point is 0.01% -> 1/10000 is one basis point /// So multiplying by the amount of basis points then dividing by 10000 /// will give us the fee as a portion of the original amount, expressed in terms of basis points. /// /// Overflows are allowed to occur at ridiculously large amounts. /// @param amount The amount to calculate the fee for /// @param feeBps The size of the fee in terms of basis points /// @return The fee function calculateFee( uint256 amount, uint256 feeBps ) public pure returns (uint256) { return (amount * feeBps) / 10_000; } /// @notice Transfers all fees or slippage collected by the router to the treasury address /// @param token The address of the token we want to transfer from the router function sweep(address token) external { if (token == NATIVE_TOKEN) { // transfer native token out of contract (bool success, ) = yodlFeeTreasury.call{ value: address(this).balance }(""); require(success, "transfer failed in sweep"); } else { // transfer ERC20 contract TransferHelper.safeTransfer( token, yodlFeeTreasury, IERC20(token).balanceOf(address(this)) ); } } /// @notice Calculates and transfers fee directly from an address to another /// @dev This can be used for directly transferring the Yodl fee from the sender to the treasury, or transferring /// the extra fee to the extra fee receiver. /// @param amount Amount from which to calculate the fee /// @param feeBps The size of the fee in basis points /// @param token The token which is being used to pay the fee. Can be an ERC20 token or the native token /// @param from The address from which we are transferring the fee /// @param to The address to which the fee will be sent /// @return The fee sent function transferFee( uint256 amount, uint256 feeBps, address token, address from, address to ) public returns (uint256) { uint256 fee = calculateFee(amount, feeBps); if (fee > 0) { if (token != NATIVE_TOKEN) { // ERC20 token if (from == address(this)) { TransferHelper.safeTransfer(token, to, fee); } else { // safeTransferFrom requires approval TransferHelper.safeTransferFrom(token, from, to, fee); } } else { require( from == address(this), "can only transfer eth from the router address" ); // Native ether (bool success, ) = to.call{value: fee}(""); require(success, "transfer failed in transferFee"); } return fee; } else { return 0; } } function verifyRateSignature( PriceFeed calldata priceFeed ) public view returns (bool) { bytes32 messageHash = keccak256( abi.encodePacked( priceFeed.currency, priceFeed.amount, priceFeed.deadline ) ); bytes32 ethSignedMessageHash = keccak256( abi.encodePacked("\x19Ethereum Signed Message:\n32", messageHash) ); if (priceFeed.deadline < block.timestamp) { return false; } return recoverSigner(ethSignedMessageHash, priceFeed.signature) == RATE_VERIFIER; } function recoverSigner( bytes32 _ethSignedMessageHash, bytes memory _signature ) private pure returns (address) { (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature); return ecrecover(_ethSignedMessageHash, v, r, s); } function splitSignature( bytes memory sig ) private pure returns (bytes32 r, bytes32 s, uint8 v) { require(sig.length == 65, "invalid signature length"); assembly { r := mload(add(sig, 32)) s := mload(add(sig, 64)) v := byte(0, mload(add(sig, 96))) } return (r, s, v); } }
// SPDX-License-Identifier: BSL-1.1 // @author samthebuilder.eth pragma solidity ^0.8.26; /** * @title IBeforeHook * @notice Interface for a hook that is called before a transfer is executed. */ interface IBeforeHook { /** * @notice Hook that is called before a transfer is executed. Hook should revert if the transfer should not be executed. * @param sender The address that initiates the transfer. * @param receiver The address that receives the transfer. * @param tokenOutAmount The amount of tokens that are transferred. * @param tokenOutAddress The address of the token that is transferred. * @param yd ID of the extension. * @param payload Any arbitrary payload attached to the transfer. * @return Any arbitrary uint256 value. */ function beforeHook( address sender, address receiver, uint256 tokenOutAmount, address tokenOutAddress, uint256 yd, bytes[] calldata payload ) external view returns (uint256); }
pragma solidity ^0.8.26; interface ICurveRouter { function exchange_multiple( address[9] calldata _route, uint256[3][4] calldata _swap_params, uint256 _amount, uint256 _expected, address[4] calldata _pools, address _receiver ) external payable returns (uint256); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; import '@uniswap/v3-periphery/contracts/interfaces/ISelfPermit.sol'; import './IV2SwapRouter.sol'; import './IV3SwapRouter.sol'; import './IApproveAndCall.sol'; import './IMulticallExtended.sol'; /// @title Router token swapping functionality interface ISwapRouter02 is IV2SwapRouter, IV3SwapRouter, IApproveAndCall, IMulticallExtended, ISelfPermit { }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // solhint-disable-next-line interface-starts-with-i interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); function getRoundData( uint80 _roundId ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.6; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; /// @title Interface for WETH9 interface IWETH9 is IERC20 { /// @notice Deposit ether to get wrapped ether function deposit() external payable; /// @notice Withdraw wrapped ether to get ether function withdraw(uint256) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.6.0; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; library TransferHelper { /// @notice Transfers tokens from the targeted address to the given destination /// @notice Errors with 'STF' if transfer fails /// @param token The contract address of the token to be transferred /// @param from The originating address from which the tokens will be transferred /// @param to The destination address of the transfer /// @param value The amount to be transferred function safeTransferFrom( address token, address from, address to, uint256 value ) internal { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF'); } /// @notice Transfers tokens from msg.sender to a recipient /// @dev Errors with ST if transfer fails /// @param token The contract address of the token which will be transferred /// @param to The recipient of the transfer /// @param value The value of the transfer function safeTransfer( address token, address to, uint256 value ) internal { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST'); } /// @notice Approves the stipulated contract to spend the given allowance in the given token /// @dev Errors with 'SA' if transfer fails /// @param token The contract address of the token to be approved /// @param to The target of the approval /// @param value The amount of the given token the target will be allowed to spend function safeApprove( address token, address to, uint256 value ) internal { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA'); } /// @notice Transfers ETH to the recipient address /// @dev Fails with `STE` /// @param to The destination of the transfer /// @param value The value to be transferred function safeTransferETH(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, 'STE'); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; /// @title Self Permit /// @notice Functionality to call permit on any EIP-2612-compliant token for use in the route interface ISelfPermit { /// @notice Permits this contract to spend a given token from `msg.sender` /// @dev The `owner` is always msg.sender and the `spender` is always address(this). /// @param token The address of the token spent /// @param value The amount that can be spent of token /// @param deadline A timestamp, the current blocktime must be less than or equal to this timestamp /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` function selfPermit( address token, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external payable; /// @notice Permits this contract to spend a given token from `msg.sender` /// @dev The `owner` is always msg.sender and the `spender` is always address(this). /// Can be used instead of #selfPermit to prevent calls from failing due to a frontrun of a call to #selfPermit /// @param token The address of the token spent /// @param value The amount that can be spent of token /// @param deadline A timestamp, the current blocktime must be less than or equal to this timestamp /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` function selfPermitIfNecessary( address token, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external payable; /// @notice Permits this contract to spend the sender's tokens for permit signatures that have the `allowed` parameter /// @dev The `owner` is always msg.sender and the `spender` is always address(this) /// @param token The address of the token spent /// @param nonce The current nonce of the owner /// @param expiry The timestamp at which the permit is no longer valid /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` function selfPermitAllowed( address token, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s ) external payable; /// @notice Permits this contract to spend the sender's tokens for permit signatures that have the `allowed` parameter /// @dev The `owner` is always msg.sender and the `spender` is always address(this) /// Can be used instead of #selfPermitAllowed to prevent calls from failing due to a frontrun of a call to #selfPermitAllowed. /// @param token The address of the token spent /// @param nonce The current nonce of the owner /// @param expiry The timestamp at which the permit is no longer valid /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s` /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s` /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v` function selfPermitAllowedIfNecessary( address token, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s ) external payable; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V2 interface IV2SwapRouter { /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @dev Setting `amountIn` to 0 will cause the contract to look up its own balance, /// and swap the entire amount, enabling contracts to send tokens before calling this function. /// @param amountIn The amount of token to swap /// @param amountOutMin The minimum amount of output that must be received /// @param path The ordered list of tokens to swap through /// @param to The recipient address /// @return amountOut The amount of the received token function swapExactTokensForTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to ) external payable returns (uint256 amountOut); /// @notice Swaps as little as possible of one token for an exact amount of another token /// @param amountOut The amount of token to swap for /// @param amountInMax The maximum amount of input that the caller will pay /// @param path The ordered list of tokens to swap through /// @param to The recipient address /// @return amountIn The amount of token to pay function swapTokensForExactTokens( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to ) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol'; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface IV3SwapRouter is IUniswapV3SwapCallback { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @dev Setting `amountIn` to 0 will cause the contract to look up its own balance, /// and swap the entire amount, enabling contracts to send tokens before calling this function. /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @dev Setting `amountIn` to 0 will cause the contract to look up its own balance, /// and swap the entire amount, enabling contracts to send tokens before calling this function. /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// that may remain in the router after the swap. /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// that may remain in the router after the swap. /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.6; pragma abicoder v2; interface IApproveAndCall { enum ApprovalType {NOT_REQUIRED, MAX, MAX_MINUS_ONE, ZERO_THEN_MAX, ZERO_THEN_MAX_MINUS_ONE} /// @dev Lens to be called off-chain to determine which (if any) of the relevant approval functions should be called /// @param token The token to approve /// @param amount The amount to approve /// @return The required approval type function getApprovalType(address token, uint256 amount) external returns (ApprovalType); /// @notice Approves a token for the maximum possible amount /// @param token The token to approve function approveMax(address token) external payable; /// @notice Approves a token for the maximum possible amount minus one /// @param token The token to approve function approveMaxMinusOne(address token) external payable; /// @notice Approves a token for zero, then the maximum possible amount /// @param token The token to approve function approveZeroThenMax(address token) external payable; /// @notice Approves a token for zero, then the maximum possible amount minus one /// @param token The token to approve function approveZeroThenMaxMinusOne(address token) external payable; /// @notice Calls the position manager with arbitrary calldata /// @param data Calldata to pass along to the position manager /// @return result The result from the call function callPositionManager(bytes memory data) external payable returns (bytes memory result); struct MintParams { address token0; address token1; uint24 fee; int24 tickLower; int24 tickUpper; uint256 amount0Min; uint256 amount1Min; address recipient; } /// @notice Calls the position manager's mint function /// @param params Calldata to pass along to the position manager /// @return result The result from the call function mint(MintParams calldata params) external payable returns (bytes memory result); struct IncreaseLiquidityParams { address token0; address token1; uint256 tokenId; uint256 amount0Min; uint256 amount1Min; } /// @notice Calls the position manager's increaseLiquidity function /// @param params Calldata to pass along to the position manager /// @return result The result from the call function increaseLiquidity(IncreaseLiquidityParams calldata params) external payable returns (bytes memory result); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; import '@uniswap/v3-periphery/contracts/interfaces/IMulticall.sol'; /// @title MulticallExtended interface /// @notice Enables calling multiple methods in a single call to the contract with optional validation interface IMulticallExtended is IMulticall { /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed /// @dev The `msg.value` should not be trusted for any method callable from multicall. /// @param deadline The time by which this function must be called before failing /// @param data The encoded function data for each of the calls to make to this contract /// @return results The results from each of the calls passed in via data function multicall(uint256 deadline, bytes[] calldata data) external payable returns (bytes[] memory results); /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed /// @dev The `msg.value` should not be trusted for any method callable from multicall. /// @param previousBlockhash The expected parent blockHash /// @param data The encoded function data for each of the calls to make to this contract /// @return results The results from each of the calls passed in via data function multicall(bytes32 previousBlockhash, bytes[] calldata data) external payable returns (bytes[] memory results); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Callback for IUniswapV3PoolActions#swap /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface interface IUniswapV3SwapCallback { /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; /// @title Multicall interface /// @notice Enables calling multiple methods in a single call to the contract interface IMulticall { /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed /// @dev The `msg.value` should not be trusted for any method callable from multicall. /// @param data The encoded function data for each of the calls to make to this contract /// @return results The results from each of the calls passed in via data function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); }
{ "remappings": [ "@chainlink/contracts/=lib/foundry-chainlink-toolkit/lib/chainlink-brownie-contracts/contracts/src/", "@openzeppelin/=lib/foundry-chainlink-toolkit/lib/openzeppelin-contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "chainlink-brownie-contracts/=lib/foundry-chainlink-toolkit/lib/chainlink-brownie-contracts/contracts/src/v0.6/vendor/@arbitrum/nitro-contracts/src/", "chainlink/=lib/chainlink/contracts/", "ds-test/=lib/foundry-chainlink-toolkit/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "foundry-chainlink-toolkit/=lib/foundry-chainlink-toolkit/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "swap-router-contracts/=lib/swap-router-contracts/contracts/", "@uniswap/swap-router-contracts/=lib/swap-router-contracts/contracts/", "v3-periphery/=lib/v3-periphery/contracts/", "@uniswap/v3-periphery/=lib/v3-periphery/", "v3-core/=lib/v3-core/", "@uniswap/v3-core/=lib/v3-core/", "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"priceFeed0","type":"address"},{"indexed":true,"internalType":"address","name":"priceFeed1","type":"address"},{"indexed":false,"internalType":"int256","name":"exchangeRate0","type":"int256"},{"indexed":false,"internalType":"int256","name":"exchangeRate1","type":"int256"}],"name":"Convert","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"currency0","type":"string"},{"indexed":true,"internalType":"address","name":"priceFeed1","type":"address"},{"indexed":false,"internalType":"int256","name":"exchangeRate0","type":"int256"},{"indexed":false,"internalType":"int256","name":"exchangeRate1","type":"int256"}],"name":"ConvertWithExternalRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fees","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"memo","type":"bytes32"}],"name":"Yodl","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"YodlNativeTokenTransfer","type":"event"},{"inputs":[],"name":"CHAINLINK_FEED","outputs":[{"internalType":"int8","name":"","type":"int8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXTERNAL_FEED","outputs":[{"internalType":"int8","name":"","type":"int8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_EXTRA_FEE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NATIVE_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NULL_FEED","outputs":[{"internalType":"int8","name":"","type":"int8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RATE_VERIFIER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"feeBps","type":"uint256"}],"name":"calculateFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"feedAddress","type":"address"},{"internalType":"int8","name":"feedType","type":"int8"},{"internalType":"string","name":"currency","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct AbstractYodlRouter.PriceFeed[2]","name":"priceFeeds","type":"tuple[2]"},{"internalType":"int256[2]","name":"prices","type":"int256[2]"}],"name":"emitConversionEvent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"feedAddress","type":"address"},{"internalType":"int8","name":"feedType","type":"int8"},{"internalType":"string","name":"currency","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct AbstractYodlRouter.PriceFeed[2]","name":"priceFeeds","type":"tuple[2]"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"exchangeRate","outputs":[{"internalType":"uint256","name":"converted","type":"uint256"},{"internalType":"address[2]","name":"priceFeedsUsed","type":"address[2]"},{"internalType":"int256[2]","name":"prices","type":"int256[2]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"feeBps","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"transferFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapRouter","outputs":[{"internalType":"contract ISwapRouter02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"feedAddress","type":"address"},{"internalType":"int8","name":"feedType","type":"int8"},{"internalType":"string","name":"currency","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct AbstractYodlRouter.PriceFeed","name":"priceFeed","type":"tuple"}],"name":"verifyRateSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wrappedNativeToken","outputs":[{"internalType":"contract IWETH9","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yodlFeeBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"yodlFeeTreasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"bytes32","name":"memo","type":"bytes32"},{"internalType":"address[9]","name":"route","type":"address[9]"},{"internalType":"uint256[3][4]","name":"swapParams","type":"uint256[3][4]"},{"internalType":"address[4]","name":"factoryAddresses","type":"address[4]"},{"components":[{"internalType":"address","name":"feedAddress","type":"address"},{"internalType":"int8","name":"feedType","type":"int8"},{"internalType":"string","name":"currency","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct AbstractYodlRouter.PriceFeed[2]","name":"priceFeeds","type":"tuple[2]"},{"internalType":"address","name":"extraFeeReceiver","type":"address"},{"internalType":"uint256","name":"extraFeeBps","type":"uint256"},{"internalType":"uint256","name":"yd","type":"uint256"},{"components":[{"internalType":"address","name":"yApp","type":"address"},{"internalType":"uint256","name":"sessionId","type":"uint256"},{"internalType":"bytes[]","name":"payload","type":"bytes[]"}],"internalType":"struct AbstractYodlRouter.YApp[]","name":"yAppList","type":"tuple[]"}],"internalType":"struct YodlCurveRouter.YodlCurveParams","name":"params","type":"tuple"}],"name":"yodlWithCurve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"memo","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"address","name":"feedAddress","type":"address"},{"internalType":"int8","name":"feedType","type":"int8"},{"internalType":"string","name":"currency","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct AbstractYodlRouter.PriceFeed[2]","name":"priceFeeds","type":"tuple[2]"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"extraFeeReceiver","type":"address"},{"internalType":"uint256","name":"extraFeeBps","type":"uint256"},{"internalType":"uint256","name":"yd","type":"uint256"},{"components":[{"internalType":"address","name":"yApp","type":"address"},{"internalType":"uint256","name":"sessionId","type":"uint256"},{"internalType":"bytes[]","name":"payload","type":"bytes[]"}],"internalType":"struct AbstractYodlRouter.YApp[]","name":"yAppList","type":"tuple[]"}],"internalType":"struct YodlTransferRouter.YodlTransferParams","name":"params","type":"tuple"}],"name":"yodlWithToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"bytes32","name":"memo","type":"bytes32"},{"internalType":"bytes","name":"path","type":"bytes"},{"components":[{"internalType":"address","name":"feedAddress","type":"address"},{"internalType":"int8","name":"feedType","type":"int8"},{"internalType":"string","name":"currency","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct AbstractYodlRouter.PriceFeed[2]","name":"priceFeeds","type":"tuple[2]"},{"internalType":"address","name":"extraFeeReceiver","type":"address"},{"internalType":"uint256","name":"extraFeeBps","type":"uint256"},{"internalType":"enum YodlUniswapRouter.SwapType","name":"swapType","type":"uint8"},{"internalType":"uint256","name":"yd","type":"uint256"},{"components":[{"internalType":"address","name":"yApp","type":"address"},{"internalType":"uint256","name":"sessionId","type":"uint256"},{"internalType":"bytes[]","name":"payload","type":"bytes[]"}],"internalType":"struct AbstractYodlRouter.YApp[]","name":"yAppList","type":"tuple[]"}],"internalType":"struct YodlUniswapRouter.YodlUniswapParams","name":"params","type":"tuple"}],"name":"yodlWithUniswap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405234801561001057600080fd5b50600480546001600160a01b03199081167399a58482bd75cbab83b27ec03ca68ff489b5788f178255600580549091167368b3465833fb72a70ecdf485e0e4c7bd8665fc4517905560408051808201909152908152637653616d60e01b602082015260009061007f9082610171565b506014600255600180546001600160a01b0319908116739c48d180e4eee0da2a899ee1e4c533ca5e92db77179091556003805490911673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc217905561022f565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806100fc57607f821691505b60208210810361011c57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561016c57806000526020600020601f840160051c810160208510156101495750805b601f840160051c820191505b818110156101695760008155600101610155565b50505b505050565b81516001600160401b0381111561018a5761018a6100d2565b61019e8161019884546100e8565b84610122565b6020601f8211600181146101d257600083156101ba5750848201515b600019600385901b1c1916600184901b178455610169565b600084815260208120601f198516915b8281101561020257878501518255602094850194600190920191016101e2565b50848210156102205786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b61396c8061023e6000396000f3fe6080604052600436106101235760003560e01c806354fd4d50116100a0578063ba54802e11610064578063ba54802e14610341578063c70994c014610354578063cf47adf614610367578063df01a8c61461038f578063ea1a0d1f146103af57600080fd5b806354fd4d50146102b457806364064789146102d657806366ef208f146102eb578063735de9f7146103015780638902b8ed1461032157600080fd5b806317fcb39b116100e757806317fcb39b146101e557806331f7d9641461021d578063345486f01461024557806334e73122146102745780634e9769e01461029457600080fd5b806301681a621461012f578063030d87401461015157806309c487d714610177578063138829a71461018d57806317a1e070146101bd57600080fd5b3661012a57005b600080fd5b34801561013b57600080fd5b5061014f61014a366004612c10565b6103c4565b005b61016461015f366004612c34565b610512565b6040519081526020015b60405180910390f35b34801561018357600080fd5b5061016460025481565b34801561019957600080fd5b506101ad6101a8366004612c6f565b610b98565b604051901515815260200161016e565b3480156101c957600080fd5b506101d2600281565b60405160009190910b815260200161016e565b3480156101f157600080fd5b50600354610205906001600160a01b031681565b6040516001600160a01b03909116815260200161016e565b34801561022957600080fd5b5061020573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b34801561025157600080fd5b50610265610260366004612ca9565b610cbc565b60405161016e93929190612cf2565b34801561028057600080fd5b5061016461028f366004612d5e565b611169565b3480156102a057600080fd5b5061014f6102af366004612f96565b61118b565b3480156102c057600080fd5b506102c961125f565b60405161016e9190613082565b3480156102e257600080fd5b506101d2600081565b3480156102f757600080fd5b5061016461138881565b34801561030d57600080fd5b50600554610205906001600160a01b031681565b34801561032d57600080fd5b50600154610205906001600160a01b031681565b61016461034f366004613095565b6112ed565b6101646103623660046130d0565b611c9b565b34801561037357600080fd5b5061020573c71f6e1e4665d319610afa526be529202ca13bb781565b34801561039b57600080fd5b506101646103aa36600461310b565b6124e0565b3480156103bb57600080fd5b506101d2600181565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03821601610495576001546040516000916001600160a01b03169047908381818185875af1925050503d8060008114610436576040519150601f19603f3d011682016040523d82523d6000602084013e61043b565b606091505b50509050806104915760405162461bcd60e51b815260206004820152601860248201527f7472616e73666572206661696c656420696e207377656570000000000000000060448201526064015b60405180910390fd5b5050565b6001546040516370a0823160e01b815230600482015261050f9183916001600160a01b03918216918316906370a0823190602401602060405180830381865afa1580156104e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050a919061316a565b61266e565b50565b600081602001356000036105595760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a5908185b5bdd5b9d60921b6044820152606401610488565b6020820135600061056d6040850185613183565b61057790806131b9565b6105889060408101906020016131cf565b60000b1415806105c7575060006105a26040850185613183565b6105b09060208101906131b9565b6105c19060408101906020016131cf565b60000b14155b15610620576105d4612bcd565b6105dc612bcd565b6105f66105ec6040870187613183565b8660200135610cbc565b919450909250905061061d61060e6040870187613183565b610617906131ea565b8361118b565b50505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6106456080850160608601612c10565b6001600160a01b03161461072057806106646080850160608601612c10565b604051636eb1769f60e11b81523360048201523060248201526001600160a01b03919091169063dd62ed3e90604401602060405180830381865afa1580156106b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d4919061316a565b101561071b5760405162461bcd60e51b8152602060048201526016602482015275696e73756666696369656e7420616c6c6f77616e636560501b6044820152606401610488565b610740565b803410156107405760405162461bcd60e51b8152600401610488906131f6565b60008335156107625761075582600254611169565b61075f9082613243565b90505b600061077460c0860160a08701612c10565b6001600160a01b031614610818576113888460c00135106107a75760405162461bcd60e51b815260040161048890613256565b61080b8260c08601356107c06080880160608901612c10565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6107e560808a0160608b01612c10565b6001600160a01b0316146107f957336107fb565b305b6103aa60c08a0160a08b01612c10565b6108159082613243565b90505b60006108248284613284565b90506000610836610100870187613297565b905011156109a65760005b61084f610100870187613297565b90508110156109a457610866610100870187613297565b82818110610876576108766131a3565b905060200281019061088891906132e0565b610896906020810190612c10565b6001600160a01b0316634d3b4c30336108b560a08a0160808b01612c10565b856108c660808c0160608d01612c10565b6108d46101008d018d613297565b888181106108e4576108e46131a3565b90506020028101906108f691906132e0565b602001356109086101008e018e613297565b89818110610918576109186131a3565b905060200281019061092a91906132e0565b610938906040810190613297565b6040518863ffffffff1660e01b815260040161095a979695949392919061331f565b602060405180830381865afa158015610977573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099b919061316a565b50600101610841565b505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6109cb6080870160608801612c10565b6001600160a01b031614610a0857610a036109ec6080870160608801612c10565b336109fd60a0890160808a01612c10565b8461276e565b610b29565b6000610a1a60a0870160808801612c10565b6001600160a01b03168260405160006040518083038185875af1925050503d8060008114610a64576040519150601f19603f3d011682016040523d82523d6000602084013e610a69565b606091505b5050905080610ad75760405162461bcd60e51b815260206004820152603460248201527f7472616e73666572206f6620746865206e617469766520746f6b656e20746f206044820152731d1a19481c9958da5c1a595b9d0819985a5b195960621b6064820152608401610488565b81610ae860a0880160808901612c10565b6001600160a01b0316336001600160a01b03167f558de3fd284a4290056c4a2ea07feaad78c886797b733dbb190a88d54d7b224160405160405180910390a4505b610b3960a0860160808701612c10565b6001600160a01b0316337f34597715a6a440e45ac583030622c386dc1299eb0d4fc56eaa9eba541462bbcd610b746080890160608a01612c10565b604051610b889190889088908c35906133f4565b60405180910390a3949350505050565b600080610ba8604084018461341a565b84606001358560800135604051602001610bc59493929190613460565b604051602081830303815290604052805190602001209050600081604051602001610c1c91907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b6040516020818303038152906040528051906020012090504284608001351015610c4a575060009392505050565b73c71f6e1e4665d319610afa526be529202ca13bb7610caa82610c7060a088018861341a565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061287892505050565b6001600160a01b031614949350505050565b6000610cc6612bcd565b610cce612bcd565b6000808080610cdd89806131b9565b610cee9060408101906020016131cf565b60000b03610d7c576000610d0560208a018a6131b9565b610d169060408101906020016131cf565b60000b03610d5657505060408051808201825260008082526020808301919091528251808401909352600180845290830152869550935091506111629050565b60019250610d6760208901896131b9565b610d75906020810190612c10565b9150610e75565b6002610d8889806131b9565b610d999060408101906020016131cf565b60000b03610e1157610dae6101a889806131b9565b610e0c5760405162461bcd60e51b815260206004820152602960248201527f496e76616c6964207369676e617475726520666f722065787465726e616c20706044820152681c9a58d9481999595960ba1b6064820152608401610488565b610e2c565b610e1b88806131b9565b610e29906020810190612c10565b91505b6000610e3b60208a018a6131b9565b610e49906020810190612c10565b6001600160a01b031614610e7557610e6460208901896131b9565b610e72906020810190612c10565b90505b6000806002610e848b806131b9565b610e959060408101906020016131cf565b60000b03610ec357610ea96012600a613561565b9150610eb58a806131b9565b606001358087529050610fa1565b836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f25919061356d565b610f339060ff16600a613561565b9150836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610f73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9791906135aa565b5050508088529150505b8415610fc35780610fb2838b6135fc565b610fbc9190613613565b9750610fdb565b81610fce828b6135fc565b610fd89190613613565b97505b6001600160a01b038316156110e457826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611028573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104c919061356d565b61105a9060ff16600a613561565b9150826001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561109a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110be91906135aa565b5050506020880181905291508190506110d7838a6135fc565b6110e19190613613565b97505b8760405180604001604052808c600060028110611103576111036131a3565b60200281019061111391906131b9565b611121906020810190612c10565b6001600160a01b0316815260209081019061113e908e018e6131b9565b61114c906020810190612c10565b6001600160a01b03169052909850965050505050505b9250925092565b600061271061117883856135fc565b6111829190613613565b90505b92915050565b81516020015160000b6001190161120b57602082015151825160409081015190516001600160a01b03909216916111c29190613635565b604080519182900382208451602080870151918552840152917fdcc70684deca576b76b466142a51be4c8d8ce48cdae1419964c0d1c4ad40ffcf91015b60405180910390a35050565b6020808301515183515183518484015160408051928352948201526001600160a01b039283169391909216917f23c9e1f4e6024ef36b16094374e2b04fc234e29ff8354c93529c23999062c9a391016111ff565b6000805461126c90613647565b80601f016020809104026020016040519081016040528092919081815260200182805461129890613647565b80156112e55780601f106112ba576101008083540402835291602001916112e5565b820191906000526020600020905b8154815290600101906020018083116112c857829003601f168201915b505050505081565b6005546000906001600160a01b03166113485760405162461bcd60e51b815260206004820152601a60248201527f756e697377617020726f75746572206e6f742070726573656e740000000000006044820152606401610488565b6000806113a761135b60a086018661341a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506113a29250505061014087016101208801613681565b6128f7565b9092509050600080806113bd60c0880188613183565b6113c790806131b9565b6113d89060408101906020016131cf565b60000b141580611417575060006113f260c0880188613183565b6114009060208101906131b9565b6114119060408101906020016131cf565b60000b14155b1561146557611424612bcd565b61142c612bcd565b61144661143c60c08a018a613183565b8960600135610cbc565b919450909250905061145e61060e60c08a018a613183565b505061146c565b5060608501355b600061147c610160880188613297565b905011156115dd5760005b611495610160880188613297565b90508110156115db576114ac610160880188613297565b828181106114bc576114bc6131a3565b90506020028101906114ce91906132e0565b6114dc906020810190612c10565b6001600160a01b0316634d3b4c30326114fb60408b0160208c01612c10565b858961150b6101608e018e613297565b8881811061151b5761151b6131a3565b905060200281019061152d91906132e0565b6020013561153f6101608f018f613297565b8981811061154f5761154f6131a3565b905060200281019061156191906132e0565b61156f906040810190613297565b6040518863ffffffff1660e01b8152600401611591979695949392919061331f565b602060405180830381865afa1580156115ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d2919061316a565b50600101611487565b505b34156116885785604001353410156116075760405162461bcd60e51b8152600401610488906131f6565b600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db087604001356040518263ffffffff1660e01b81526004016000604051808303818588803b15801561165b57600080fd5b505af115801561166f573d6000803e3d6000fd5b50506003546001600160a01b0316955061169892505050565b611698833230896040013561276e565b6005546116b49084906001600160a01b03166040890135612960565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038616016116ed57506003546001600160a01b0316935060015b600061170161014089016101208a01613681565b6001811115611712576117126136a2565b03611871576040805160e0810182526001600160a01b03808716825287166020820152600091810161178461174a60a08c018c61341a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612a5992505050565b62ffffff90811682523060208084019190915260408084018890528c81013560608086019190915260006080958601526005548251635023b4df60e01b815287516001600160a01b03908116600483015294880151851660248201529287015190941660448301528501518216606482015292840151608484015260a084015160a484015260c0840151811660c48401529293509190911690635023b4df9060e4016020604051808303816000875af1158015611845573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611869919061316a565b93505061199d565b6000808061188260a08b018b61341a565b81019061188f91906136c9565b5060408051608081019091526bffffffffffffffffffffffff1960608e811b821660a08401526001600160e81b031960e887811b821660b486015286831b841660b786015285901b1660cb8401528d901b1660ce8201529296509094509250600091508060e2810160408051601f198184030181529181529082523060208301528181018990528d81013560609092019190915260055490516304dc09a360e11b81529192506001600160a01b0316906309b813469061195390849060040161371c565b6020604051808303816000875af1158015611972573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611996919061316a565b9650505050505b8015611a1957600354604051632e1a7d4d60e01b8152600481018490526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b1580156119e957600080fd5b505af11580156119fd573d6000803e3d6000fd5b5050505073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee94505b6000608088013515611a3e57611a3183600254611169565b611a3b9082613243565b90505b6000611a516101008a0160e08b01612c10565b6001600160a01b031614611aaf5761138888610100013510611a855760405162461bcd60e51b815260040161048890613256565b611aa2836101008a01803590899030906103aa9060e08f01612c10565b611aac9082613243565b90505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03871601611be8576000611ae660408a0160208b01612c10565b6001600160a01b0316611af98386613284565b604051600081818185875af1925050503d8060008114611b35576040519150601f19603f3d011682016040523d82523d6000602084013e611b3a565b606091505b5050905080611b7d5760405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b6044820152606401610488565b611b878285613284565b611b9760408b0160208c01612c10565b6001600160a01b0316611bad60208c018c612c10565b6001600160a01b03167f558de3fd284a4290056c4a2ea07feaad78c886797b733dbb190a88d54d7b224160405160405180910390a450611c06565b611c0686611bfc60408b0160208c01612c10565b61050a8487613284565b611c166040890160208a01612c10565b6001600160a01b0316611c2c60208a018a612c10565b6001600160a01b03167f34597715a6a440e45ac583030622c386dc1299eb0d4fc56eaa9eba541462bbcd8886858d60800135604051611c6e94939291906133f4565b60405180910390a3600554611c8f9086906001600160a01b03166000612960565b50919695505050505050565b6004546000906001600160a01b0316611cf65760405162461bcd60e51b815260206004820152601860248201527f637572766520726f75746572206e6f742070726573656e7400000000000000006044820152606401610488565b600080611d2e8460a0016009806020026040519081016040528092919082600960200280828437600092019190915250612a79915050565b9092509050600080611d446103c0870187613183565b611d4e90806131b9565b611d5f9060408101906020016131cf565b60000b141580611d9f57506000611d7a6103c0870187613183565b611d889060208101906131b9565b611d999060408101906020016131cf565b60000b14155b15611def57611dac612bcd565b611db4612bcd565b611dcf611dc56103c0890189613183565b8860600135610cbc565b9194509092509050611de861060e6103c0890189613183565b5050611df6565b5060608401355b6000611e06610440870187613297565b90501115611f675760005b611e1f610440870187613297565b9050811015611f6557611e36610440870187613297565b82818110611e4657611e466131a3565b9050602002810190611e5891906132e0565b611e66906020810190612c10565b6001600160a01b0316634d3b4c3033611e8560408a0160208b01612c10565b8588611e956104408d018d613297565b88818110611ea557611ea56131a3565b9050602002810190611eb791906132e0565b60200135611ec96104408e018e613297565b89818110611ed957611ed96131a3565b9050602002810190611eeb91906132e0565b611ef9906040810190613297565b6040518863ffffffff1660e01b8152600401611f1b979695949392919061331f565b602060405180830381865afa158015611f38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5c919061316a565b50600101611e11565b505b3415612012578460400135341015611f915760405162461bcd60e51b8152600401610488906131f6565b600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db086604001356040518263ffffffff1660e01b81526004016000604051808303818588803b158015611fe557600080fd5b505af1158015611ff9573d6000803e3d6000fd5b50506003546001600160a01b0316945061202292505050565b612022823330886040013561276e565b60045461203e9083906001600160a01b03166040880135612960565b6004805460408051630651cb3560e01b81526000936001600160a01b0390931692630651cb35926120889260a08c01926101c08d01928d01359189916103408f01913091016137a6565b6020604051808303816000875af11580156120a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120cb919061316a565b90508181101561212e5760405162461bcd60e51b815260206004820152602860248201527f616d6f756e744f7574206973206c657373207468656e20616d6f756e744f7574604482015267115e1c1958dd195960c21b6064820152608401610488565b60006080870135156121535761214683600254611169565b6121509082613243565b90505b600061216761040089016103e08a01612c10565b6001600160a01b0316146121c6576113888761040001351061219b5760405162461bcd60e51b815260040161048890613256565b6121b9836104008901803590889030906103aa906103e08e01612c10565b6121c39082613243565b90505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03861601612452576003546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612234573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612258919061316a565b9050838110156122c15760405162461bcd60e51b815260206004820152602e60248201527f577261707065642062616c616e6365206973206c657373207468656e20616d6f60448201526d1d5b9d13dd5d115e1c1958dd195960921b6064820152608401610488565b600354604051632e1a7d4d60e01b8152600481018390526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561230757600080fd5b505af115801561231b573d6000803e3d6000fd5b506000925061233391505060408a0160208b01612c10565b6001600160a01b03166123468487613284565b604051600081818185875af1925050503d8060008114612382576040519150601f19603f3d011682016040523d82523d6000602084013e612387565b606091505b50509050806123e65760405162461bcd60e51b815260206004820152602560248201527f7472616e73666572206f66206e617469766520746f2072656365697665722066604482015264185a5b195960da1b6064820152608401610488565b6123f08386613284565b61240060408b0160208c01612c10565b6001600160a01b031661241660208c018c612c10565b6001600160a01b03167f558de3fd284a4290056c4a2ea07feaad78c886797b733dbb190a88d54d7b224160405160405180910390a45050612466565b61246685611bfc60408a0160208b01612c10565b6124766040880160208901612c10565b6001600160a01b031661248c6020890189612c10565b6001600160a01b03167f34597715a6a440e45ac583030622c386dc1299eb0d4fc56eaa9eba541462bbcd8786858c608001356040516124ce94939291906133f4565b60405180910390a35095945050505050565b6000806124ed8787611169565b9050801561265f576001600160a01b03851673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461254557306001600160a01b038516036125395761253485848361266e565b612658565b6125348585858461276e565b6001600160a01b03841630146125b35760405162461bcd60e51b815260206004820152602d60248201527f63616e206f6e6c79207472616e73666572206574682066726f6d20746865207260448201526c6f75746572206164647265737360981b6064820152608401610488565b6000836001600160a01b03168260405160006040518083038185875af1925050503d8060008114612600576040519150601f19603f3d011682016040523d82523d6000602084013e612605565b606091505b50509050806126565760405162461bcd60e51b815260206004820152601e60248201527f7472616e73666572206661696c656420696e207472616e7366657246656500006044820152606401610488565b505b9050612665565b60009150505b95945050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916126ca9190613635565b6000604051808303816000865af19150503d8060008114612707576040519150601f19603f3d011682016040523d82523d6000602084013e61270c565b606091505b50915091508180156127365750805115806127365750808060200190518101906127369190613849565b6127675760405162461bcd60e51b815260206004820152600260248201526114d560f21b6044820152606401610488565b5050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916127d29190613635565b6000604051808303816000865af19150503d806000811461280f576040519150601f19603f3d011682016040523d82523d6000602084013e612814565b606091505b509150915081801561283e57508051158061283e57508080602001905181019061283e9190613849565b6128705760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b6044820152606401610488565b505050505050565b60008060008061288785612b5b565b6040805160008152602081018083528b905260ff8316918101919091526060810184905260808101839052929550909350915060019060a0016020604051602081039080840390855afa1580156128e2573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b60008080808085600181111561290f5761290f6136a2565b036129355785806020019051810190612928919061386b565b9193509091506129539050565b8580602001905181019061294991906138b8565b9395509293505050505b90925090505b9250929050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916129bc9190613635565b6000604051808303816000865af19150503d80600081146129f9576040519150601f19603f3d011682016040523d82523d6000602084013e6129fe565b606091505b5091509150818015612a28575080511580612a28575080806020019051810190612a289190613849565b6127675760405162461bcd60e51b8152602060048201526002602482015261534160f01b6044820152606401610488565b60008082806020019051810190612a70919061386b565b50949350505050565b80516040820151600091829160045b60028110612afb57600086612a9e8360026135fc565b60098110612aae57612aae6131a3565b60200201516001600160a01b031614612ae95785612acd8260026135fc565b60098110612add57612add6131a3565b60200201519150612afb565b80612af38161391f565b915050612a88565b506001600160a01b038116612b525760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420726f75746520706172616d657465720000000000000000006044820152606401610488565b94909350915050565b60008060008351604114612bb15760405162461bcd60e51b815260206004820152601860248201527f696e76616c6964207369676e6174757265206c656e67746800000000000000006044820152606401610488565b50505060208101516040820151606083015160001a9193909250565b60405180604001604052806002906020820280368337509192915050565b6001600160a01b038116811461050f57600080fd5b8035612c0b81612beb565b919050565b600060208284031215612c2257600080fd5b8135612c2d81612beb565b9392505050565b600060208284031215612c4657600080fd5b81356001600160401b03811115612c5c57600080fd5b82016101208185031215612c2d57600080fd5b600060208284031215612c8157600080fd5b81356001600160401b03811115612c9757600080fd5b820160c08185031215612c2d57600080fd5b60008060408385031215612cbc57600080fd5b82356001600160401b03811115612cd257600080fd5b830160408101851015612ce457600080fd5b946020939093013593505050565b83815260a08101602082018460005b6002811015612d295781516001600160a01b0316835260209283019290910190600101612d01565b505050606082018360005b6002811015612d53578151835260209283019290910190600101612d34565b505050949350505050565b60008060408385031215612d7157600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b0381118282101715612db857612db8612d80565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612de657612de6612d80565b604052919050565b60006001600160401b03821115612e0757612e07612d80565b5060051b90565b8035600081900b8114612c0b57600080fd5b600082601f830112612e3157600080fd5b8135602083016000806001600160401b03841115612e5157612e51612d80565b50601f8301601f1916602001612e6681612dbe565b915050828152858383011115612e7b57600080fd5b82826020830137600092810160200192909252509392505050565b6000612eaa612ea56002612dee565b612dbe565b9050806040830184811115612ebe57600080fd5b835b81811015612f8d5780356001600160401b03811115612ede57600080fd5b850160c08188031215612ef057600080fd5b612ef8612d96565b612f0182612c00565b8152612f0f60208301612e0e565b602082015260408201356001600160401b03811115612f2d57600080fd5b612f3989828501612e20565b604083015250606082810135908201526080808301359082015260a08201356001600160401b03811115612f6c57600080fd5b612f7889828501612e20565b60a08301525084525060209283019201612ec0565b50505092915050565b60008060608385031215612fa957600080fd5b82356001600160401b03811115612fbf57600080fd5b8301601f81018513612fd057600080fd5b612fda8582612e96565b92505083603f840112612fec57600080fd5b612ff66040612dbe565b80606085018681111561300857600080fd5b602086015b8181101561302557803584526020938401930161300d565b5093969095509350505050565b60005b8381101561304d578181015183820152602001613035565b50506000910152565b6000815180845261306e816020860160208601613032565b601f01601f19169290920160200192915050565b6020815260006111826020830184613056565b6000602082840312156130a757600080fd5b81356001600160401b038111156130bd57600080fd5b82016101808185031215612c2d57600080fd5b6000602082840312156130e257600080fd5b81356001600160401b038111156130f857600080fd5b82016104608185031215612c2d57600080fd5b600080600080600060a0868803121561312357600080fd5b8535945060208601359350604086013561313c81612beb565b9250606086013561314c81612beb565b9150608086013561315c81612beb565b809150509295509295909350565b60006020828403121561317c57600080fd5b5051919050565b60008235603e1983360301811261319957600080fd5b9190910192915050565b634e487b7160e01b600052603260045260246000fd5b6000823560be1983360301811261319957600080fd5b6000602082840312156131e157600080fd5b61118282612e0e565b60006111853683612e96565b60208082526019908201527f696e73756666696369656e74206761732070726f766964656400000000000000604082015260600190565b634e487b7160e01b600052601160045260246000fd5b808201808211156111855761118561322d565b6020808252601490820152730caf0e8e4c28ccaca84e0e640e8dede40d0d2ced60631b604082015260600190565b818103818111156111855761118561322d565b6000808335601e198436030181126132ae57600080fd5b8301803591506001600160401b038211156132c857600080fd5b6020019150600581901b360382131561295957600080fd5b60008235605e1983360301811261319957600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038881168252878116602083015260408201879052851660608201526080810184905260c060a082018190528101829052600060e0600584901b830181019083018583601e1936839003015b878210156133e25786850360df19018452823581811261339157600080fd5b89016020810190356001600160401b038111156133ad57600080fd5b8036038213156133bc57600080fd5b6133c78782846132f6565b96505050602083019250602084019350600182019150613372565b50929c9b505050505050505050505050565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6000808335601e1984360301811261343157600080fd5b8301803591506001600160401b0382111561344b57600080fd5b60200191503681900382131561295957600080fd5b838582379092019081526020810191909152604001919050565b6001815b60018411156134b5578085048111156134995761349961322d565b60018416156134a757908102905b60019390931c92800261347e565b935093915050565b6000826134cc57506001611185565b816134d957506000611185565b81600181146134ef57600281146134f957613515565b6001915050611185565b60ff84111561350a5761350a61322d565b50506001821b611185565b5060208310610133831016604e8410600b8410161715613538575081810a611185565b613545600019848461347a565b80600019048211156135595761355961322d565b029392505050565b600061118283836134bd565b60006020828403121561357f57600080fd5b815160ff81168114612c2d57600080fd5b805169ffffffffffffffffffff81168114612c0b57600080fd5b600080600080600060a086880312156135c257600080fd5b6135cb86613590565b602087015160408801516060890151929750909550935091506135f060808701613590565b90509295509295909350565b80820281158282048414176111855761118561322d565b60008261363057634e487b7160e01b600052601260045260246000fd5b500490565b60008251613199818460208701613032565b600181811c9082168061365b57607f821691505b60208210810361367b57634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561369357600080fd5b813560028110612c2d57600080fd5b634e487b7160e01b600052602160045260246000fd5b62ffffff8116811461050f57600080fd5b600080600080600060a086880312156136e157600080fd5b85356136ec81612beb565b945060208601356136fc816136b8565b9350604086013561370c81612beb565b9250606086013561314c816136b8565b60208152600082516080602084015261373860a0840182613056565b905060018060a01b03602085015116604084015260408401516060840152606084015160808401528091505092915050565b8060005b60048110156137a057813561378281612beb565b6001600160a01b03168452602093840193919091019060010161376e565b50505050565b6103808101818860005b60098110156137e25781356137c481612beb565b6001600160a01b0316835260209283019291909101906001016137b0565b50505061012082018760005b600481101561380f57606082843760609283019291909101906001016137ee565b505050856102a0830152846102c083015261382e6102e083018561376a565b6001600160a01b038316610360830152979650505050505050565b60006020828403121561385b57600080fd5b81518015158114612c2d57600080fd5b60008060006060848603121561388057600080fd5b835161388b81612beb565b602085015190935061389c816136b8565b60408501519092506138ad81612beb565b809150509250925092565b600080600080600060a086880312156138d057600080fd5b85516138db81612beb565b60208701519095506138ec816136b8565b60408701519094506138fd81612beb565b606087015190935061390e816136b8565b608087015190925061315c81612beb565b60008161392e5761392e61322d565b50600019019056fea2646970667358221220956f66333c077731890db96e2fccd42811dfcd8e16b954aa31cdc965e99c911c64736f6c634300081a0033
Deployed Bytecode
0x6080604052600436106101235760003560e01c806354fd4d50116100a0578063ba54802e11610064578063ba54802e14610341578063c70994c014610354578063cf47adf614610367578063df01a8c61461038f578063ea1a0d1f146103af57600080fd5b806354fd4d50146102b457806364064789146102d657806366ef208f146102eb578063735de9f7146103015780638902b8ed1461032157600080fd5b806317fcb39b116100e757806317fcb39b146101e557806331f7d9641461021d578063345486f01461024557806334e73122146102745780634e9769e01461029457600080fd5b806301681a621461012f578063030d87401461015157806309c487d714610177578063138829a71461018d57806317a1e070146101bd57600080fd5b3661012a57005b600080fd5b34801561013b57600080fd5b5061014f61014a366004612c10565b6103c4565b005b61016461015f366004612c34565b610512565b6040519081526020015b60405180910390f35b34801561018357600080fd5b5061016460025481565b34801561019957600080fd5b506101ad6101a8366004612c6f565b610b98565b604051901515815260200161016e565b3480156101c957600080fd5b506101d2600281565b60405160009190910b815260200161016e565b3480156101f157600080fd5b50600354610205906001600160a01b031681565b6040516001600160a01b03909116815260200161016e565b34801561022957600080fd5b5061020573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b34801561025157600080fd5b50610265610260366004612ca9565b610cbc565b60405161016e93929190612cf2565b34801561028057600080fd5b5061016461028f366004612d5e565b611169565b3480156102a057600080fd5b5061014f6102af366004612f96565b61118b565b3480156102c057600080fd5b506102c961125f565b60405161016e9190613082565b3480156102e257600080fd5b506101d2600081565b3480156102f757600080fd5b5061016461138881565b34801561030d57600080fd5b50600554610205906001600160a01b031681565b34801561032d57600080fd5b50600154610205906001600160a01b031681565b61016461034f366004613095565b6112ed565b6101646103623660046130d0565b611c9b565b34801561037357600080fd5b5061020573c71f6e1e4665d319610afa526be529202ca13bb781565b34801561039b57600080fd5b506101646103aa36600461310b565b6124e0565b3480156103bb57600080fd5b506101d2600181565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03821601610495576001546040516000916001600160a01b03169047908381818185875af1925050503d8060008114610436576040519150601f19603f3d011682016040523d82523d6000602084013e61043b565b606091505b50509050806104915760405162461bcd60e51b815260206004820152601860248201527f7472616e73666572206661696c656420696e207377656570000000000000000060448201526064015b60405180910390fd5b5050565b6001546040516370a0823160e01b815230600482015261050f9183916001600160a01b03918216918316906370a0823190602401602060405180830381865afa1580156104e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050a919061316a565b61266e565b50565b600081602001356000036105595760405162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a5908185b5bdd5b9d60921b6044820152606401610488565b6020820135600061056d6040850185613183565b61057790806131b9565b6105889060408101906020016131cf565b60000b1415806105c7575060006105a26040850185613183565b6105b09060208101906131b9565b6105c19060408101906020016131cf565b60000b14155b15610620576105d4612bcd565b6105dc612bcd565b6105f66105ec6040870187613183565b8660200135610cbc565b919450909250905061061d61060e6040870187613183565b610617906131ea565b8361118b565b50505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6106456080850160608601612c10565b6001600160a01b03161461072057806106646080850160608601612c10565b604051636eb1769f60e11b81523360048201523060248201526001600160a01b03919091169063dd62ed3e90604401602060405180830381865afa1580156106b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d4919061316a565b101561071b5760405162461bcd60e51b8152602060048201526016602482015275696e73756666696369656e7420616c6c6f77616e636560501b6044820152606401610488565b610740565b803410156107405760405162461bcd60e51b8152600401610488906131f6565b60008335156107625761075582600254611169565b61075f9082613243565b90505b600061077460c0860160a08701612c10565b6001600160a01b031614610818576113888460c00135106107a75760405162461bcd60e51b815260040161048890613256565b61080b8260c08601356107c06080880160608901612c10565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6107e560808a0160608b01612c10565b6001600160a01b0316146107f957336107fb565b305b6103aa60c08a0160a08b01612c10565b6108159082613243565b90505b60006108248284613284565b90506000610836610100870187613297565b905011156109a65760005b61084f610100870187613297565b90508110156109a457610866610100870187613297565b82818110610876576108766131a3565b905060200281019061088891906132e0565b610896906020810190612c10565b6001600160a01b0316634d3b4c30336108b560a08a0160808b01612c10565b856108c660808c0160608d01612c10565b6108d46101008d018d613297565b888181106108e4576108e46131a3565b90506020028101906108f691906132e0565b602001356109086101008e018e613297565b89818110610918576109186131a3565b905060200281019061092a91906132e0565b610938906040810190613297565b6040518863ffffffff1660e01b815260040161095a979695949392919061331f565b602060405180830381865afa158015610977573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099b919061316a565b50600101610841565b505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6109cb6080870160608801612c10565b6001600160a01b031614610a0857610a036109ec6080870160608801612c10565b336109fd60a0890160808a01612c10565b8461276e565b610b29565b6000610a1a60a0870160808801612c10565b6001600160a01b03168260405160006040518083038185875af1925050503d8060008114610a64576040519150601f19603f3d011682016040523d82523d6000602084013e610a69565b606091505b5050905080610ad75760405162461bcd60e51b815260206004820152603460248201527f7472616e73666572206f6620746865206e617469766520746f6b656e20746f206044820152731d1a19481c9958da5c1a595b9d0819985a5b195960621b6064820152608401610488565b81610ae860a0880160808901612c10565b6001600160a01b0316336001600160a01b03167f558de3fd284a4290056c4a2ea07feaad78c886797b733dbb190a88d54d7b224160405160405180910390a4505b610b3960a0860160808701612c10565b6001600160a01b0316337f34597715a6a440e45ac583030622c386dc1299eb0d4fc56eaa9eba541462bbcd610b746080890160608a01612c10565b604051610b889190889088908c35906133f4565b60405180910390a3949350505050565b600080610ba8604084018461341a565b84606001358560800135604051602001610bc59493929190613460565b604051602081830303815290604052805190602001209050600081604051602001610c1c91907f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c810191909152603c0190565b6040516020818303038152906040528051906020012090504284608001351015610c4a575060009392505050565b73c71f6e1e4665d319610afa526be529202ca13bb7610caa82610c7060a088018861341a565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061287892505050565b6001600160a01b031614949350505050565b6000610cc6612bcd565b610cce612bcd565b6000808080610cdd89806131b9565b610cee9060408101906020016131cf565b60000b03610d7c576000610d0560208a018a6131b9565b610d169060408101906020016131cf565b60000b03610d5657505060408051808201825260008082526020808301919091528251808401909352600180845290830152869550935091506111629050565b60019250610d6760208901896131b9565b610d75906020810190612c10565b9150610e75565b6002610d8889806131b9565b610d999060408101906020016131cf565b60000b03610e1157610dae6101a889806131b9565b610e0c5760405162461bcd60e51b815260206004820152602960248201527f496e76616c6964207369676e617475726520666f722065787465726e616c20706044820152681c9a58d9481999595960ba1b6064820152608401610488565b610e2c565b610e1b88806131b9565b610e29906020810190612c10565b91505b6000610e3b60208a018a6131b9565b610e49906020810190612c10565b6001600160a01b031614610e7557610e6460208901896131b9565b610e72906020810190612c10565b90505b6000806002610e848b806131b9565b610e959060408101906020016131cf565b60000b03610ec357610ea96012600a613561565b9150610eb58a806131b9565b606001358087529050610fa1565b836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f25919061356d565b610f339060ff16600a613561565b9150836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610f73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9791906135aa565b5050508088529150505b8415610fc35780610fb2838b6135fc565b610fbc9190613613565b9750610fdb565b81610fce828b6135fc565b610fd89190613613565b97505b6001600160a01b038316156110e457826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611028573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104c919061356d565b61105a9060ff16600a613561565b9150826001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561109a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110be91906135aa565b5050506020880181905291508190506110d7838a6135fc565b6110e19190613613565b97505b8760405180604001604052808c600060028110611103576111036131a3565b60200281019061111391906131b9565b611121906020810190612c10565b6001600160a01b0316815260209081019061113e908e018e6131b9565b61114c906020810190612c10565b6001600160a01b03169052909850965050505050505b9250925092565b600061271061117883856135fc565b6111829190613613565b90505b92915050565b81516020015160000b6001190161120b57602082015151825160409081015190516001600160a01b03909216916111c29190613635565b604080519182900382208451602080870151918552840152917fdcc70684deca576b76b466142a51be4c8d8ce48cdae1419964c0d1c4ad40ffcf91015b60405180910390a35050565b6020808301515183515183518484015160408051928352948201526001600160a01b039283169391909216917f23c9e1f4e6024ef36b16094374e2b04fc234e29ff8354c93529c23999062c9a391016111ff565b6000805461126c90613647565b80601f016020809104026020016040519081016040528092919081815260200182805461129890613647565b80156112e55780601f106112ba576101008083540402835291602001916112e5565b820191906000526020600020905b8154815290600101906020018083116112c857829003601f168201915b505050505081565b6005546000906001600160a01b03166113485760405162461bcd60e51b815260206004820152601a60248201527f756e697377617020726f75746572206e6f742070726573656e740000000000006044820152606401610488565b6000806113a761135b60a086018661341a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506113a29250505061014087016101208801613681565b6128f7565b9092509050600080806113bd60c0880188613183565b6113c790806131b9565b6113d89060408101906020016131cf565b60000b141580611417575060006113f260c0880188613183565b6114009060208101906131b9565b6114119060408101906020016131cf565b60000b14155b1561146557611424612bcd565b61142c612bcd565b61144661143c60c08a018a613183565b8960600135610cbc565b919450909250905061145e61060e60c08a018a613183565b505061146c565b5060608501355b600061147c610160880188613297565b905011156115dd5760005b611495610160880188613297565b90508110156115db576114ac610160880188613297565b828181106114bc576114bc6131a3565b90506020028101906114ce91906132e0565b6114dc906020810190612c10565b6001600160a01b0316634d3b4c30326114fb60408b0160208c01612c10565b858961150b6101608e018e613297565b8881811061151b5761151b6131a3565b905060200281019061152d91906132e0565b6020013561153f6101608f018f613297565b8981811061154f5761154f6131a3565b905060200281019061156191906132e0565b61156f906040810190613297565b6040518863ffffffff1660e01b8152600401611591979695949392919061331f565b602060405180830381865afa1580156115ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d2919061316a565b50600101611487565b505b34156116885785604001353410156116075760405162461bcd60e51b8152600401610488906131f6565b600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db087604001356040518263ffffffff1660e01b81526004016000604051808303818588803b15801561165b57600080fd5b505af115801561166f573d6000803e3d6000fd5b50506003546001600160a01b0316955061169892505050565b611698833230896040013561276e565b6005546116b49084906001600160a01b03166040890135612960565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038616016116ed57506003546001600160a01b0316935060015b600061170161014089016101208a01613681565b6001811115611712576117126136a2565b03611871576040805160e0810182526001600160a01b03808716825287166020820152600091810161178461174a60a08c018c61341a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612a5992505050565b62ffffff90811682523060208084019190915260408084018890528c81013560608086019190915260006080958601526005548251635023b4df60e01b815287516001600160a01b03908116600483015294880151851660248201529287015190941660448301528501518216606482015292840151608484015260a084015160a484015260c0840151811660c48401529293509190911690635023b4df9060e4016020604051808303816000875af1158015611845573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611869919061316a565b93505061199d565b6000808061188260a08b018b61341a565b81019061188f91906136c9565b5060408051608081019091526bffffffffffffffffffffffff1960608e811b821660a08401526001600160e81b031960e887811b821660b486015286831b841660b786015285901b1660cb8401528d901b1660ce8201529296509094509250600091508060e2810160408051601f198184030181529181529082523060208301528181018990528d81013560609092019190915260055490516304dc09a360e11b81529192506001600160a01b0316906309b813469061195390849060040161371c565b6020604051808303816000875af1158015611972573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611996919061316a565b9650505050505b8015611a1957600354604051632e1a7d4d60e01b8152600481018490526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b1580156119e957600080fd5b505af11580156119fd573d6000803e3d6000fd5b5050505073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee94505b6000608088013515611a3e57611a3183600254611169565b611a3b9082613243565b90505b6000611a516101008a0160e08b01612c10565b6001600160a01b031614611aaf5761138888610100013510611a855760405162461bcd60e51b815260040161048890613256565b611aa2836101008a01803590899030906103aa9060e08f01612c10565b611aac9082613243565b90505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03871601611be8576000611ae660408a0160208b01612c10565b6001600160a01b0316611af98386613284565b604051600081818185875af1925050503d8060008114611b35576040519150601f19603f3d011682016040523d82523d6000602084013e611b3a565b606091505b5050905080611b7d5760405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b6044820152606401610488565b611b878285613284565b611b9760408b0160208c01612c10565b6001600160a01b0316611bad60208c018c612c10565b6001600160a01b03167f558de3fd284a4290056c4a2ea07feaad78c886797b733dbb190a88d54d7b224160405160405180910390a450611c06565b611c0686611bfc60408b0160208c01612c10565b61050a8487613284565b611c166040890160208a01612c10565b6001600160a01b0316611c2c60208a018a612c10565b6001600160a01b03167f34597715a6a440e45ac583030622c386dc1299eb0d4fc56eaa9eba541462bbcd8886858d60800135604051611c6e94939291906133f4565b60405180910390a3600554611c8f9086906001600160a01b03166000612960565b50919695505050505050565b6004546000906001600160a01b0316611cf65760405162461bcd60e51b815260206004820152601860248201527f637572766520726f75746572206e6f742070726573656e7400000000000000006044820152606401610488565b600080611d2e8460a0016009806020026040519081016040528092919082600960200280828437600092019190915250612a79915050565b9092509050600080611d446103c0870187613183565b611d4e90806131b9565b611d5f9060408101906020016131cf565b60000b141580611d9f57506000611d7a6103c0870187613183565b611d889060208101906131b9565b611d999060408101906020016131cf565b60000b14155b15611def57611dac612bcd565b611db4612bcd565b611dcf611dc56103c0890189613183565b8860600135610cbc565b9194509092509050611de861060e6103c0890189613183565b5050611df6565b5060608401355b6000611e06610440870187613297565b90501115611f675760005b611e1f610440870187613297565b9050811015611f6557611e36610440870187613297565b82818110611e4657611e466131a3565b9050602002810190611e5891906132e0565b611e66906020810190612c10565b6001600160a01b0316634d3b4c3033611e8560408a0160208b01612c10565b8588611e956104408d018d613297565b88818110611ea557611ea56131a3565b9050602002810190611eb791906132e0565b60200135611ec96104408e018e613297565b89818110611ed957611ed96131a3565b9050602002810190611eeb91906132e0565b611ef9906040810190613297565b6040518863ffffffff1660e01b8152600401611f1b979695949392919061331f565b602060405180830381865afa158015611f38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5c919061316a565b50600101611e11565b505b3415612012578460400135341015611f915760405162461bcd60e51b8152600401610488906131f6565b600360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db086604001356040518263ffffffff1660e01b81526004016000604051808303818588803b158015611fe557600080fd5b505af1158015611ff9573d6000803e3d6000fd5b50506003546001600160a01b0316945061202292505050565b612022823330886040013561276e565b60045461203e9083906001600160a01b03166040880135612960565b6004805460408051630651cb3560e01b81526000936001600160a01b0390931692630651cb35926120889260a08c01926101c08d01928d01359189916103408f01913091016137a6565b6020604051808303816000875af11580156120a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120cb919061316a565b90508181101561212e5760405162461bcd60e51b815260206004820152602860248201527f616d6f756e744f7574206973206c657373207468656e20616d6f756e744f7574604482015267115e1c1958dd195960c21b6064820152608401610488565b60006080870135156121535761214683600254611169565b6121509082613243565b90505b600061216761040089016103e08a01612c10565b6001600160a01b0316146121c6576113888761040001351061219b5760405162461bcd60e51b815260040161048890613256565b6121b9836104008901803590889030906103aa906103e08e01612c10565b6121c39082613243565b90505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03861601612452576003546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612234573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612258919061316a565b9050838110156122c15760405162461bcd60e51b815260206004820152602e60248201527f577261707065642062616c616e6365206973206c657373207468656e20616d6f60448201526d1d5b9d13dd5d115e1c1958dd195960921b6064820152608401610488565b600354604051632e1a7d4d60e01b8152600481018390526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561230757600080fd5b505af115801561231b573d6000803e3d6000fd5b506000925061233391505060408a0160208b01612c10565b6001600160a01b03166123468487613284565b604051600081818185875af1925050503d8060008114612382576040519150601f19603f3d011682016040523d82523d6000602084013e612387565b606091505b50509050806123e65760405162461bcd60e51b815260206004820152602560248201527f7472616e73666572206f66206e617469766520746f2072656365697665722066604482015264185a5b195960da1b6064820152608401610488565b6123f08386613284565b61240060408b0160208c01612c10565b6001600160a01b031661241660208c018c612c10565b6001600160a01b03167f558de3fd284a4290056c4a2ea07feaad78c886797b733dbb190a88d54d7b224160405160405180910390a45050612466565b61246685611bfc60408a0160208b01612c10565b6124766040880160208901612c10565b6001600160a01b031661248c6020890189612c10565b6001600160a01b03167f34597715a6a440e45ac583030622c386dc1299eb0d4fc56eaa9eba541462bbcd8786858c608001356040516124ce94939291906133f4565b60405180910390a35095945050505050565b6000806124ed8787611169565b9050801561265f576001600160a01b03851673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461254557306001600160a01b038516036125395761253485848361266e565b612658565b6125348585858461276e565b6001600160a01b03841630146125b35760405162461bcd60e51b815260206004820152602d60248201527f63616e206f6e6c79207472616e73666572206574682066726f6d20746865207260448201526c6f75746572206164647265737360981b6064820152608401610488565b6000836001600160a01b03168260405160006040518083038185875af1925050503d8060008114612600576040519150601f19603f3d011682016040523d82523d6000602084013e612605565b606091505b50509050806126565760405162461bcd60e51b815260206004820152601e60248201527f7472616e73666572206661696c656420696e207472616e7366657246656500006044820152606401610488565b505b9050612665565b60009150505b95945050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916126ca9190613635565b6000604051808303816000865af19150503d8060008114612707576040519150601f19603f3d011682016040523d82523d6000602084013e61270c565b606091505b50915091508180156127365750805115806127365750808060200190518101906127369190613849565b6127675760405162461bcd60e51b815260206004820152600260248201526114d560f21b6044820152606401610488565b5050505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916127d29190613635565b6000604051808303816000865af19150503d806000811461280f576040519150601f19603f3d011682016040523d82523d6000602084013e612814565b606091505b509150915081801561283e57508051158061283e57508080602001905181019061283e9190613849565b6128705760405162461bcd60e51b815260206004820152600360248201526229aa2360e91b6044820152606401610488565b505050505050565b60008060008061288785612b5b565b6040805160008152602081018083528b905260ff8316918101919091526060810184905260808101839052929550909350915060019060a0016020604051602081039080840390855afa1580156128e2573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b60008080808085600181111561290f5761290f6136a2565b036129355785806020019051810190612928919061386b565b9193509091506129539050565b8580602001905181019061294991906138b8565b9395509293505050505b90925090505b9250929050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916129bc9190613635565b6000604051808303816000865af19150503d80600081146129f9576040519150601f19603f3d011682016040523d82523d6000602084013e6129fe565b606091505b5091509150818015612a28575080511580612a28575080806020019051810190612a289190613849565b6127675760405162461bcd60e51b8152602060048201526002602482015261534160f01b6044820152606401610488565b60008082806020019051810190612a70919061386b565b50949350505050565b80516040820151600091829160045b60028110612afb57600086612a9e8360026135fc565b60098110612aae57612aae6131a3565b60200201516001600160a01b031614612ae95785612acd8260026135fc565b60098110612add57612add6131a3565b60200201519150612afb565b80612af38161391f565b915050612a88565b506001600160a01b038116612b525760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420726f75746520706172616d657465720000000000000000006044820152606401610488565b94909350915050565b60008060008351604114612bb15760405162461bcd60e51b815260206004820152601860248201527f696e76616c6964207369676e6174757265206c656e67746800000000000000006044820152606401610488565b50505060208101516040820151606083015160001a9193909250565b60405180604001604052806002906020820280368337509192915050565b6001600160a01b038116811461050f57600080fd5b8035612c0b81612beb565b919050565b600060208284031215612c2257600080fd5b8135612c2d81612beb565b9392505050565b600060208284031215612c4657600080fd5b81356001600160401b03811115612c5c57600080fd5b82016101208185031215612c2d57600080fd5b600060208284031215612c8157600080fd5b81356001600160401b03811115612c9757600080fd5b820160c08185031215612c2d57600080fd5b60008060408385031215612cbc57600080fd5b82356001600160401b03811115612cd257600080fd5b830160408101851015612ce457600080fd5b946020939093013593505050565b83815260a08101602082018460005b6002811015612d295781516001600160a01b0316835260209283019290910190600101612d01565b505050606082018360005b6002811015612d53578151835260209283019290910190600101612d34565b505050949350505050565b60008060408385031215612d7157600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b0381118282101715612db857612db8612d80565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612de657612de6612d80565b604052919050565b60006001600160401b03821115612e0757612e07612d80565b5060051b90565b8035600081900b8114612c0b57600080fd5b600082601f830112612e3157600080fd5b8135602083016000806001600160401b03841115612e5157612e51612d80565b50601f8301601f1916602001612e6681612dbe565b915050828152858383011115612e7b57600080fd5b82826020830137600092810160200192909252509392505050565b6000612eaa612ea56002612dee565b612dbe565b9050806040830184811115612ebe57600080fd5b835b81811015612f8d5780356001600160401b03811115612ede57600080fd5b850160c08188031215612ef057600080fd5b612ef8612d96565b612f0182612c00565b8152612f0f60208301612e0e565b602082015260408201356001600160401b03811115612f2d57600080fd5b612f3989828501612e20565b604083015250606082810135908201526080808301359082015260a08201356001600160401b03811115612f6c57600080fd5b612f7889828501612e20565b60a08301525084525060209283019201612ec0565b50505092915050565b60008060608385031215612fa957600080fd5b82356001600160401b03811115612fbf57600080fd5b8301601f81018513612fd057600080fd5b612fda8582612e96565b92505083603f840112612fec57600080fd5b612ff66040612dbe565b80606085018681111561300857600080fd5b602086015b8181101561302557803584526020938401930161300d565b5093969095509350505050565b60005b8381101561304d578181015183820152602001613035565b50506000910152565b6000815180845261306e816020860160208601613032565b601f01601f19169290920160200192915050565b6020815260006111826020830184613056565b6000602082840312156130a757600080fd5b81356001600160401b038111156130bd57600080fd5b82016101808185031215612c2d57600080fd5b6000602082840312156130e257600080fd5b81356001600160401b038111156130f857600080fd5b82016104608185031215612c2d57600080fd5b600080600080600060a0868803121561312357600080fd5b8535945060208601359350604086013561313c81612beb565b9250606086013561314c81612beb565b9150608086013561315c81612beb565b809150509295509295909350565b60006020828403121561317c57600080fd5b5051919050565b60008235603e1983360301811261319957600080fd5b9190910192915050565b634e487b7160e01b600052603260045260246000fd5b6000823560be1983360301811261319957600080fd5b6000602082840312156131e157600080fd5b61118282612e0e565b60006111853683612e96565b60208082526019908201527f696e73756666696369656e74206761732070726f766964656400000000000000604082015260600190565b634e487b7160e01b600052601160045260246000fd5b808201808211156111855761118561322d565b6020808252601490820152730caf0e8e4c28ccaca84e0e640e8dede40d0d2ced60631b604082015260600190565b818103818111156111855761118561322d565b6000808335601e198436030181126132ae57600080fd5b8301803591506001600160401b038211156132c857600080fd5b6020019150600581901b360382131561295957600080fd5b60008235605e1983360301811261319957600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038881168252878116602083015260408201879052851660608201526080810184905260c060a082018190528101829052600060e0600584901b830181019083018583601e1936839003015b878210156133e25786850360df19018452823581811261339157600080fd5b89016020810190356001600160401b038111156133ad57600080fd5b8036038213156133bc57600080fd5b6133c78782846132f6565b96505050602083019250602084019350600182019150613372565b50929c9b505050505050505050505050565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6000808335601e1984360301811261343157600080fd5b8301803591506001600160401b0382111561344b57600080fd5b60200191503681900382131561295957600080fd5b838582379092019081526020810191909152604001919050565b6001815b60018411156134b5578085048111156134995761349961322d565b60018416156134a757908102905b60019390931c92800261347e565b935093915050565b6000826134cc57506001611185565b816134d957506000611185565b81600181146134ef57600281146134f957613515565b6001915050611185565b60ff84111561350a5761350a61322d565b50506001821b611185565b5060208310610133831016604e8410600b8410161715613538575081810a611185565b613545600019848461347a565b80600019048211156135595761355961322d565b029392505050565b600061118283836134bd565b60006020828403121561357f57600080fd5b815160ff81168114612c2d57600080fd5b805169ffffffffffffffffffff81168114612c0b57600080fd5b600080600080600060a086880312156135c257600080fd5b6135cb86613590565b602087015160408801516060890151929750909550935091506135f060808701613590565b90509295509295909350565b80820281158282048414176111855761118561322d565b60008261363057634e487b7160e01b600052601260045260246000fd5b500490565b60008251613199818460208701613032565b600181811c9082168061365b57607f821691505b60208210810361367b57634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561369357600080fd5b813560028110612c2d57600080fd5b634e487b7160e01b600052602160045260246000fd5b62ffffff8116811461050f57600080fd5b600080600080600060a086880312156136e157600080fd5b85356136ec81612beb565b945060208601356136fc816136b8565b9350604086013561370c81612beb565b9250606086013561314c816136b8565b60208152600082516080602084015261373860a0840182613056565b905060018060a01b03602085015116604084015260408401516060840152606084015160808401528091505092915050565b8060005b60048110156137a057813561378281612beb565b6001600160a01b03168452602093840193919091019060010161376e565b50505050565b6103808101818860005b60098110156137e25781356137c481612beb565b6001600160a01b0316835260209283019291909101906001016137b0565b50505061012082018760005b600481101561380f57606082843760609283019291909101906001016137ee565b505050856102a0830152846102c083015261382e6102e083018561376a565b6001600160a01b038316610360830152979650505050505050565b60006020828403121561385b57600080fd5b81518015158114612c2d57600080fd5b60008060006060848603121561388057600080fd5b835161388b81612beb565b602085015190935061389c816136b8565b60408501519092506138ad81612beb565b809150509250925092565b600080600080600060a086880312156138d057600080fd5b85516138db81612beb565b60208701519095506138ec816136b8565b60408701519094506138fd81612beb565b606087015190935061390e816136b8565b608087015190925061315c81612beb565b60008161392e5761392e61322d565b50600019019056fea2646970667358221220956f66333c077731890db96e2fccd42811dfcd8e16b954aa31cdc965e99c911c64736f6c634300081a0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
POL | 100.00% | $0.512772 | 0.0173 | $0.008852 |
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.