More Info
Private Name Tags
ContractCreator
Latest 5 from a total of 5 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Push Incoming Or... | 59554643 | 139 days ago | IN | 0 POL | 0.00712529 | ||||
Push Orders | 59554630 | 139 days ago | IN | 0 POL | 0.00232195 | ||||
Push Incoming Or... | 57220808 | 198 days ago | IN | 0 POL | 0.00600155 | ||||
Push Incoming Or... | 57189357 | 199 days ago | IN | 0 POL | 0.0065517 | ||||
Push Orders | 57189249 | 199 days ago | IN | 0 POL | 0.00252819 |
Latest 11 internal transactions
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
59555006 | 139 days ago | 0.73069026 POL | ||||
59555006 | 139 days ago | 0.73069026 POL | ||||
59549503 | 139 days ago | 0.7113005 POL | ||||
59549503 | 139 days ago | 0.7113005 POL | ||||
57220884 | 198 days ago | 0.54842419 POL | ||||
57220884 | 198 days ago | 0.54842419 POL | ||||
57189385 | 199 days ago | 0.50690328 POL | ||||
57189385 | 199 days ago | 0.50690328 POL | ||||
57188000 | 199 days ago | 0.53155518 POL | ||||
57188000 | 199 days ago | 0.53155518 POL | ||||
57186500 | 199 days ago | Contract Creation | 0 POL |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
RemoteOmnichainMessenger
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import {IOrderBook} from "./interfaces/IOrderBook.sol"; import {IPhutureOnMessageCallback} from "./interfaces/IPhutureOnMessageCallback.sol"; import {IRemoteOmnichainMessenger} from "./interfaces/IRemoteOmnichainMessenger.sol"; import {IVault} from "./interfaces/IVault.sol"; import {IEscrowDeployer} from "./escrow/interfaces/IEscrowDeployer.sol"; import {RebalancingLib} from "./libraries/RebalancingLib.sol"; import {OrderLib} from "./libraries/OrderLib.sol"; import {OmnichainMessenger} from "./OmnichainMessenger.sol"; /// @title RemoteOmnichainMessenger /// @notice A messenger contract for the Remote chain /// @dev Methods of this contract are not intended for direct usage contract RemoteOmnichainMessenger is IRemoteOmnichainMessenger, OmnichainMessenger { /// @dev The address of the Vault contract IVault internal immutable vault; /// @notice Thrown when there are pending orders to be pushed error PushOrders(); /// @dev Thrown when the provided msg.value is insufficient for the operation error InsufficientValue(); constructor( address owner, address _stargateComposer, address payable _endpoint, address _vault, uint16 _homeEid, address _sgETH, NativeInfo memory _nativeInfo ) OmnichainMessenger(owner, _stargateComposer, _endpoint, _homeEid, _sgETH, _nativeInfo) { vault = IVault(_vault); } /// @notice Sends the currencies hash to the Homechain. /// /// @dev Reverts if the homechain endpoint ID is not set. /// /// @param info The result of registering currencies in the Vault contract. /// @param refundAddress The address to refund the native fee to. /// @param lzParams LayerZero params. function sendCurrenciesHash( IVault.RegisterCurrenciesResult calldata info, address payable refundAddress, LzParams calldata lzParams ) external payable onlyOwner { // sload home endpoint id uint16 eid = homeEid; // store the balance before the lzSend (not couting the value passed to the method) uint256 balanceBefore = address(this).balance - msg.value; // send REGISTER_CURRENCY message to homechain using LayerZero _lzSend( eid, _getPathOrRevert(eid), abi.encode(REGISTER_CURRENCY, _fillCurrenciesMetadata(info)), refundAddress, lzParams.zroPaymentAddress, lzParams.options[0] ); // only amount passed to the method should be used for the lzSend if (address(this).balance < balanceBefore) revert InsufficientValue(); } /// @notice Finishes the rebalancing process and sends the result hash to the specified Omnichain instance /// /// @dev Reverts if homechain and/or remote chain endpoint IDs are not set /// /// @param orderBookParams The parameters for finishing the order execution in the OrderBook contract /// @param params The parameters for ending the rebalancing phase in the Vault contract /// @param refundAddress The address to refund the payment to /// @param sgParams Stargate params /// @param lzParams LayerZero params. `REMOVE_DUST_ORDERS`'s options go first, `FINISH_REBALANCING` - the last on function finishVaultRebalancing( IOrderBook.FinishOrderExecutionParams calldata orderBookParams, IVault.EndRebalancingParams calldata params, SgParams[] calldata sgParams, LzParams calldata lzParams, address payable refundAddress ) external payable onlyOwner { // check if there are no hash of orders for the current chain if (ordersHashOf[block.chainid] != bytes32(0)) revert PushOrders(); // gather pending orders from order book and distribute them across the chains using Stargate _distributeOrders(orderBook.finishOrderExecution(orderBookParams), sgParams, lzParams); // sload home endpoint id uint16 eid = homeEid; // finish rebalancing phase on Vault contract and get the result hash bytes32 resultHash = vault.finishRebalancingPhase(params); // send FINISH_REBALANCING message to homechain using LayerZero _lzSend( eid, _getPathOrRevert(eid), abi.encode(FINISH_REBALANCING, HashedResult(block.chainid, resultHash)), refundAddress, lzParams.zroPaymentAddress, lzParams.options[lzParams.options.length - 1] ); } /// @notice Pushes the orders for the current chain /// /// @param chainOrders The orders to be pushed for the current chain function pushOrders(RebalancingLib.ChainOrders memory chainOrders) external { // validate orders hash if (keccak256(abi.encode(chainOrders)) != ordersHashOf[block.chainid]) revert OrderHashMismatch(); // delete orders hash – it should be used only once delete ordersHashOf[block.chainid]; emit OrdersHashClear(block.chainid); // inject local buy currency into orders OrderLib.Order[] memory orders = chainOrders.orders; _injectLocalBuyCurrency(orders); // set orders in the order book orderBook.setOrders(chainOrders.incomingOrders, orders); } /// @dev Handle messages received from the Homechain via LayerZero /// @param message The received message – abi encoded packet type and payload function _lzReceive(bytes calldata message) internal override { // decode packet type uint8 packetType = uint8(uint256(bytes32(message[:32]))); if (packetType == TRANSFER_SNAPSHOT) { // TRANSFER_SNAPSHOT packet payload: original msg.sender from Homechain, kAmount redeemed (, address sender, uint256 kAmount) = abi.decode(message, (uint8, address, uint256)); // get address of escrow account for sender, notice that escrow is not being deployed here (address escrow,) = escrowDeployer.escrowOf(sender); // transfer kAmount of latest snapshot to escrow of sender vault.transferLatestSnapshot(escrow, kAmount); } else if (packetType == TRADE_SNAPSHOT) { // TRADE_SNAPSHOT packet payload: original msg.sender from Homechain, callback for RemoteEscrow (, address sender, bytes memory callback) = abi.decode(message, (uint8, address, bytes)); // sload an escrow deployer IEscrowDeployer deployer = escrowDeployer; // get address of escrow account for sender and whether it is deployed (address escrow, bool deployed) = deployer.escrowOf(sender); if (!deployed) { // if escrow is not deployed, deploy it try deployer.deploy(sender) {} catch { return; } } // call phutureOnMessageCallbackV1 on deployed escrow try IPhutureOnMessageCallback(escrow).phutureOnMessageCallbackV1(0, 0, callback) {} catch {} } else if (packetType == TRANSFER_AND_TRADE_SNAPSHOT) { // TRANSFER_AND_TRADE_SNAPSHOT packet payload: original msg.sender from Homechain, kAmount redeemed, callback for RemoteEscrow (, address sender, uint256 kAmount, bytes memory callback) = abi.decode(message, (uint8, address, uint256, bytes)); // sload an escrow deployer IEscrowDeployer deployer = escrowDeployer; // get address of escrow account for sender and whether it is deployed (address escrow, bool deployed) = deployer.escrowOf(sender); // transfer kAmount of latest snapshot to escrow of sender uint256 snapshot = vault.transferLatestSnapshot(escrow, kAmount); if (!deployed) { // if escrow is not deployed, deploy it try deployer.deploy(sender) {} catch { return; } } // notice, transferred snapshot is passed to the callback for instant withdrawal try IPhutureOnMessageCallback(escrow).phutureOnMessageCallbackV1(snapshot, kAmount, callback) {} catch {} } else if (packetType == START_REBALANCING) { // PLACE_ORDERS packet payload: StartRebalancingResult {withdrawal; ordersHash;} (, bytes32 ordersHash, IVault.CurrencyWithdrawal memory withdrawal) = abi.decode(message, (uint8, bytes32, IVault.CurrencyWithdrawal)); // save orders hash for validation on the next push ordersHashOf[block.chainid] = ordersHash; // start rebalancing phase on Vault contract vault.startRebalancingPhase(withdrawal); } else if (packetType == START_RESERVE_REBALANCING) { // START_RESERVE_REBALANCING packet payload: incomingOrders (, uint256 incomingOrders) = abi.decode(message, (uint8, uint256)); // start rebalancing phase on Vault contract IVault.CurrencyWithdrawal memory withdrawal; vault.startRebalancingPhase(withdrawal); orderBook.setOrders(incomingOrders, new OrderLib.Order[](0)); } else if (packetType == REMOVE_DUST_ORDERS) { // REMOVE_DUST_ORDERS packet payload: incomingOrders (, uint256 incomingOrders) = abi.decode(message, (uint8, uint256)); // remove dust orders from the order book orderBook.removeDustOrders(incomingOrders); } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; import {Currency} from "../libraries/CurrencyLib.sol"; import {OrderLib} from "../libraries/OrderLib.sol"; /// @title IOrderBook interface interface IOrderBook { struct TradeParams { address target; bytes data; } struct BoughtOrder { // Bought amount of local buy currency, sell amount on the remote uint256 amount; // Buy currency on the remote Currency buyCurrency; } struct PendingOrder { uint256 chainId; Currency currency; uint256 totalBought; BoughtOrder[] orders; } struct FinishOrderExecutionParams { OrderLib.OrderId[] orderIds; uint256[] idIndices; uint256[] pendingOrderCounts; } struct ExecuteOrderParams { OrderLib.OrderId orderId; uint96 sell; TradeParams tradeParams; bytes payload; } event OrderFilled(bytes32 indexed id, uint256 sold, uint256 bought); function receiveIncomingOrders(OrderLib.Order[] calldata orders, Currency currency, uint256 amount) external; function removeDustOrders(uint256 _incomingOrders) external; function setOrders(uint256 _incomingOrders, OrderLib.Order[] calldata orders) external; /// @notice Execute the given local order /// @param params Execute order data function executeOrder(ExecuteOrderParams calldata params) external; function finishOrderExecution(FinishOrderExecutionParams calldata params) external returns (PendingOrder[] memory pendingOrders); function updateFundManager(address fundManager, bool isAllowed) external; function setMessenger(address messenger) external; function setPriceOracle(address priceOracle) external; function setMaxSlippageInBP(uint16 maxSlippageInBP) external; function orderOf(OrderLib.OrderId calldata orderIdParams) external view returns (uint96 amount); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; interface IPhutureOnMessageCallback { function phutureOnMessageCallbackV1(uint256 snapshot, uint256 kAmount, bytes calldata data) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; import {IOmnichainMessenger} from "./IOmnichainMessenger.sol"; import {IVault} from "./IVault.sol"; import {RebalancingLib} from "../libraries/RebalancingLib.sol"; interface IRemoteOmnichainMessenger is IOmnichainMessenger { function sendCurrenciesHash( IVault.RegisterCurrenciesResult calldata result, address payable refundAddress, LzParams calldata lzParams ) external payable; function pushOrders(RebalancingLib.ChainOrders calldata chainOrders) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; import {Currency} from "../libraries/CurrencyLib.sol"; import {a160u96} from "../utils/a160u96.sol"; interface IVault { struct CurrencyWithdrawal { uint256[] currencyIndexSet; uint96[] amounts; } struct SnapshotAnatomy { a160u96[] currencies; uint256[] currencyIndexSet; } struct EndRebalancingParams { a160u96[] anatomyCurrencies; SnapshotAnatomy newAnatomy; CurrencyWithdrawal withdrawals; uint256 lastKBalance; Currency[] currencies; } struct RebalancingResult { uint256 chainId; uint256 snapshot; uint256[] currencyIdSet; a160u96[] currencies; } struct RegisterCurrenciesResult { Currency[] currencies; bytes32 currenciesHash; } function setOrderBook(address _orderBook) external; function setMessenger(address _messenger) external; function startRebalancingPhase(CurrencyWithdrawal calldata withdrawals) external; function finishRebalancingPhase(EndRebalancingParams calldata params) external returns (bytes32); function transferLatestSnapshot(address recipient, uint256 kAmountWads) external returns (uint256); function withdraw(uint256 snapshot, uint256 kAmount, address recipient) external; function registerCurrencies(Currency[] calldata currencies) external returns (RegisterCurrenciesResult memory); function donate(Currency currency, bytes memory data) external; function consume(Currency currency, uint96 amount, address target, bytes calldata data) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; /// @title IEscrowDeployer /// @dev Interface for the EscrowDeployer contract, which manages the deployment and tracking of Escrow contracts interface IEscrowDeployer { /// @notice Deploys a new Escrow contract for the specified user /// /// @param user The address of the user for whom the Escrow contract is deployed /// /// @return escrow The address of the newly deployed Escrow contract function deploy(address user) external returns (address escrow); /// @notice Retrieves the address and deployment status of the Escrow contract associated with the given owner /// /// @param owner The address of the owner for whom to retrieve the Escrow contract information /// /// @return escrow The address of the Escrow contract associated with the owner /// @return deployed A boolean indicating whether the Escrow contract has been deployed for the owner function escrowOf(address owner) external view returns (address escrow, bool deployed); /// @notice Retrieves the address of the Messenger contract associated with the EscrowDeployer /// /// @return The address of the Messenger contract function messenger() external view returns (address); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import {SafeCastLib} from "solmate/utils/SafeCastLib.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import {Currency} from "./CurrencyLib.sol"; import {BitSet} from "./BitSet.sol"; import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol"; import {OrderLib} from "./OrderLib.sol"; import {PriceLib} from "../price-oracles/libraries/PriceLib.sol"; import {StackLib} from "./StackLib.sol"; import {IVault} from "../interfaces/IVault.sol"; import {IConfigBuilder} from "../interfaces/IConfigBuilder.sol"; /// @title RebalancingLib /// @notice Library for managing order creation during rebalancing library RebalancingLib { using SafeCastLib for *; using BitSet for *; using FixedPointMathLib for *; using PriceLib for *; using StackLib for StackLib.Node; /// @dev Represents the orders for a specific chain struct ChainOrders { OrderLib.Order[] orders; uint128 incomingOrders; } /// @dev Represents the valuation information for the assets struct ValuationInfo { uint96[] balances; uint256[] prices; uint256 totalValuation; } /// @dev Represents the result of the rebalancing process struct RebalancingResult { ChainOrders[] chainOrders; IVault.CurrencyWithdrawal[] withdrawals; uint256[] chainIdSet; uint256[] counters; } struct RebalancingVars { StackLib.Node sellDeltas; StackLib.Node buyDeltas; uint256 targetInBase; uint256 currentInBase; uint256 i; uint256 j; uint256 priorChainIndex; uint256 activeChainIndex; uint256 currencyIndex; uint256 orderIndex; uint256 weightIndex; bytes32 chainsHash; bytes32 currenciesHash; uint256[] counters; bool priorChain; bool activeChain; bool priorAsset; } struct ReserveRebalancingVars { uint256 orderCount; uint96 utilized; uint256 i; uint256 j; uint256 lastIndex; uint256 orderIndex; uint256 weightIndex; bytes32 chainsHash; } uint256 internal constant MAX_WEIGHT = type(uint16).max; /// @notice Thrown when the currencies hash does not match the expected value /// @param chainId The chainId that the hash is associated with error CurrenciesHashMismatch(uint256 chainId); /// @notice Thrown when the total weight of the rebalancing weights is not equal to MAX_WEIGHT error TotalWeight(); /// @notice Thrown when there are unutilized weights in the rebalancing weights error UnutilizedWeights(); /// @notice Thrown when the chains hash does not match the expected value error ChainsHashMismatch(); /// @notice Previews the rebalancing orders based on the given parameters /// /// @param currenciesHashOf The mapping of chain IDs to their currencies hash /// @param valuationInfo The valuation information for the assets /// @param params The start rebalancing parameters /// @param chainsHash The expected hash of the chain IDs /// /// @return result The rebalancing result containing the chain orders, withdrawals, and counters function previewRebalancingOrders( mapping(uint256 => bytes32) storage currenciesHashOf, ValuationInfo memory valuationInfo, IConfigBuilder.StartRebalancingParams calldata params, bytes32 chainsHash ) internal view returns (RebalancingResult memory result) { result.chainIdSet = params.anatomy.chainIdSet.addAll(params.newAnatomy.chainIdSet); result.chainOrders = new ChainOrders[](result.chainIdSet.size()); result.withdrawals = new IVault.CurrencyWithdrawal[](result.chainOrders.length); result.counters = new uint256[](result.chainOrders.length); RebalancingVars memory vars; for (; vars.i < params.chainIds.length;) { vars.chainsHash = keccak256(abi.encode(vars.chainsHash, params.chainIds[vars.i])); vars.priorChain = params.anatomy.chainIdSet.contains(vars.i); vars.activeChain = params.newAnatomy.chainIdSet.contains(vars.i); if (vars.activeChain || vars.priorChain) { if (vars.priorChain) { result.chainOrders[vars.orderIndex].orders = new OrderLib.Order[](params.orderCounts[vars.orderIndex]); result.withdrawals[vars.orderIndex] = IVault.CurrencyWithdrawal( BitSet.create(params.currencies[vars.orderIndex].length), new uint96[](params.anatomy.currencyIdSets[vars.priorChainIndex].size()) ); } IVault.CurrencyWithdrawal memory withdrawal = result.withdrawals[vars.orderIndex]; vars.currenciesHash = bytes32(0); Currency[] calldata currencies = params.currencies[vars.orderIndex]; for (vars.j = 0; vars.j < currencies.length;) { vars.currenciesHash = keccak256(abi.encode(vars.currenciesHash, currencies[vars.j])); vars.priorAsset = vars.priorChain && params.anatomy.currencyIdSets[vars.priorChainIndex].contains(vars.j); vars.targetInBase = vars.activeChain && params.newAnatomy.currencyIdSets[vars.activeChainIndex].contains(vars.j) ? valuationInfo.totalValuation.mulDivUp(params.newWeights[vars.weightIndex++], MAX_WEIGHT) : 0; vars.currentInBase = vars.priorAsset ? valuationInfo.balances[vars.currencyIndex].convertToBaseUp( valuationInfo.prices[vars.currencyIndex] ) : 0; if (vars.currentInBase < vars.targetInBase) { uint256 delta = vars.targetInBase - vars.currentInBase; vars.buyDeltas = vars.buyDeltas.push(delta, vars.orderIndex, currencies[vars.j], params.chainIds[vars.i]); } else if (vars.currentInBase > vars.targetInBase) { // result will never exceed type(uint96).max. uint96 assets = uint96( valuationInfo.balances[vars.currencyIndex].mulDivDown( vars.currentInBase - vars.targetInBase, vars.currentInBase ) ); if (assets != 0) { vars.sellDeltas = vars.sellDeltas.push( vars.currentInBase - vars.targetInBase, assets, vars.orderIndex, currencies[vars.j], valuationInfo.prices[vars.currencyIndex] ); withdrawal.amounts[withdrawal.currencyIndexSet.size()] = assets; withdrawal.currencyIndexSet.add(vars.j); } } unchecked { if (vars.priorAsset) ++vars.currencyIndex; ++vars.j; } } if (vars.currenciesHash != currenciesHashOf[vars.i]) { revert CurrenciesHashMismatch(params.chainIds[vars.i]); } (vars.sellDeltas, vars.buyDeltas) = _createOrders(result.chainOrders, vars.sellDeltas, vars.buyDeltas, result.counters); unchecked { if (vars.priorChain) ++vars.priorChainIndex; if (vars.activeChain) ++vars.activeChainIndex; ++vars.orderIndex; } } unchecked { ++vars.i; } } if (params.newWeights.length != vars.weightIndex) revert UnutilizedWeights(); if (vars.chainsHash != chainsHash) revert ChainsHashMismatch(); } /// @notice Previews the reserve rebalancing orders based on the given parameters /// /// @param currenciesHashOf The mapping of chain IDs to their currencies hash /// @param weights The array of weights for the reserve assets /// @param params The start reserve rebalancing parameters /// @param reserveAmount The total amount of reserve assets /// @param reserve The reserve currency /// @param chainsHash The expected hash of the chain IDs /// /// @return orders The array of chain orders for the reserve rebalancing function previewReserveRebalancingOrders( mapping(uint256 => bytes32) storage currenciesHashOf, uint256[] memory weights, IConfigBuilder.StartReserveRebalancingParams calldata params, uint96 reserveAmount, Currency reserve, bytes32 chainsHash ) internal view returns (ChainOrders[] memory orders) { orders = new ChainOrders[](params.anatomy.chainIdSet.size()); ReserveRebalancingVars memory vars; vars.orderCount = weights.length; vars.lastIndex = vars.orderCount - 1; orders[0].orders = new OrderLib.Order[](vars.orderCount); for (; vars.i < params.chainIds.length; ++vars.i) { vars.chainsHash = keccak256(abi.encode(vars.chainsHash, params.chainIds[vars.i])); if (!params.anatomy.chainIdSet.contains(vars.i)) continue; bytes32 currenciesHash; Currency[] calldata currencies = params.currencies[vars.orderIndex]; for (vars.j = 0; vars.j < currencies.length; ++vars.j) { currenciesHash = keccak256(abi.encode(currenciesHash, currencies[vars.j])); if (params.anatomy.currencyIdSets[vars.orderIndex].contains(vars.j)) { uint96 orderSellAmount = vars.weightIndex == vars.lastIndex ? reserveAmount - vars.utilized : reserveAmount.mulDivDown(weights[vars.weightIndex], MAX_WEIGHT).safeCastTo96(); orders[0].orders[vars.weightIndex] = OrderLib.Order( orderSellAmount, OrderLib.OrderId(reserve, currencies[vars.j], currencies[vars.j], params.chainIds[vars.i]) ); unchecked { if (vars.orderIndex != 0 && orderSellAmount != 0) { ++orders[vars.orderIndex].incomingOrders; } vars.utilized += orderSellAmount; ++vars.weightIndex; } } } if (currenciesHash != currenciesHashOf[vars.i]) revert CurrenciesHashMismatch(params.chainIds[vars.i]); unchecked { ++vars.orderIndex; } } if (vars.chainsHash != chainsHash) revert ChainsHashMismatch(); } /// @notice Checks if the total weight is equal to the maximum weight /// /// @dev This function reverts if the sum of the weights is not equal to MAX_WEIGHT /// /// @param weights The array of weights to check function checkTotalWeight(uint256[] calldata weights) internal pure { uint256 total; for (uint256 i; i < weights.length; ++i) { total += weights[i]; } if (total != MAX_WEIGHT) revert TotalWeight(); } /// @dev Creates the rebalancing orders by matching sell and buy deltas /// /// @param orders The array of chain orders to populate /// @param sellDeltas The stack of sell deltas /// @param buyDeltas The stack of buy deltas /// @param counters The array of order counters for each chain /// /// @return The updated sell and buy delta stacks after creating the orders function _createOrders( ChainOrders[] memory orders, StackLib.Node memory sellDeltas, StackLib.Node memory buyDeltas, uint256[] memory counters ) internal pure returns (StackLib.Node memory, StackLib.Node memory) { // while one of lists is not empty while (sellDeltas.notEmpty() && buyDeltas.notEmpty()) { // get first nodes from both lists StackLib.Data memory sell = sellDeltas.peek(); StackLib.Data memory buy = buyDeltas.peek(); uint256 fill = Math.min(sell.delta, buy.delta); sell.delta -= fill; buy.delta -= fill; uint256 sellAmount = Math.min(fill.convertToAssetsUp(sell.data), sell.availableAssets); sell.availableAssets -= sellAmount; orders[sell.orderIndex].orders[counters[sell.orderIndex]++] = OrderLib.Order( sellAmount.safeCastTo96(), OrderLib.OrderId(sell.currency, buy.currency, buy.currency, buy.data) ); // increment "fence" counter if (buy.orderIndex != sell.orderIndex && sellAmount != 0) { ++orders[buy.orderIndex].incomingOrders; } // remove nodes with zero delta. Notice, both deltas can be set to zero. if (sell.delta == 0) { sellDeltas = sellDeltas.pop(); } if (buy.delta == 0) { buyDeltas = buyDeltas.pop(); } } return (sellDeltas, buyDeltas); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import {Currency} from "./CurrencyLib.sol"; /// @title OrderLib /// @notice Library for managing orders library OrderLib { struct OrderId { // Sell currency of order Currency sellCurrency; // Local buy currency of order Currency localBuyCurrency; // Final destination buy currency of order Currency finalDestinationBuyCurrency; // Final destination chainId of order uint256 finalDestinationChainId; } struct Order { // Sell amount of order uint96 sellAmount; // Id params of order OrderId idParams; } struct OrderRegistry { // Sell amount of given order mapping(bytes32 => uint96) orderOf; // Hash of registry state bytes32 ordersHash; } /// @notice Emitted when a new order is created event NewOrder( uint256 sellAmount, Currency indexed sellCurrency, Currency localBuyCurrency, Currency indexed finalDestinationBuyCurrency, uint256 finalDestinationChainId ); /// @notice Thrown when there's a mismatch in order hashes error OrderHashMismatch(); /// @notice Thrown when an order is not filled /// @param id The id of the order that was not filled error OrderNotFilled(bytes32 id); /// @notice Sets multiple orders in the registry /// /// @param self The order registry where orders are stored /// @param orders An array of orders to set in the registry function set(OrderRegistry storage self, Order[] calldata orders) internal { bytes32 newHash = self.ordersHash; for (uint256 i; i < orders.length; ++i) { if (orders[i].sellAmount == 0) continue; OrderId calldata params = orders[i].idParams; // don't need to create order for the same currency within a single chain, as it's already in the final destination if (params.sellCurrency != params.localBuyCurrency || params.finalDestinationChainId != block.chainid) { bytes32 idKey = id(params); newHash = keccak256(abi.encode(newHash, idKey)); self.orderOf[idKey] += orders[i].sellAmount; emit NewOrder( orders[i].sellAmount, params.sellCurrency, params.localBuyCurrency, params.finalDestinationBuyCurrency, params.finalDestinationChainId ); } } self.ordersHash = newHash; } /// @notice Fills a specific order from the registry /// /// @param self The order registry /// @param orderId The id params of the order to fill /// @param sell The sell amount of the order function fill(OrderRegistry storage self, OrderId calldata orderId, uint96 sell) internal { self.orderOf[id(orderId)] -= sell; } /// @notice Resets the orders in the registry /// /// @param self The order registry to reset /// /// @param orderIds An array of order id parameters to reset function reset(OrderRegistry storage self, OrderId[] calldata orderIds) internal { bytes32 ordersHash; for (uint256 i; i < orderIds.length; ++i) { bytes32 idKey = id(orderIds[i]); ordersHash = keccak256(abi.encode(ordersHash, idKey)); if (self.orderOf[idKey] != 0) revert OrderNotFilled(idKey); } if (ordersHash != self.ordersHash) revert OrderHashMismatch(); self.ordersHash = bytes32(0); } /// @notice Retrieves the sell amount of a specific order /// @param self The order registry /// /// @param orderId The id parameters of the order to retrieve /// /// @return The sell amount of the specified order function get(OrderRegistry storage self, OrderId calldata orderId) internal view returns (uint96) { return self.orderOf[id(orderId)]; } /// @dev Generates a unique id for an order based on its parameters /// /// @param self The order id parameters /// /// @return A unique bytes32 id for the order function id(OrderId calldata self) internal pure returns (bytes32) { return keccak256(abi.encode(self)); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {ICurrencyMetadata} from "./interfaces/ICurrencyMetadata.sol"; import {IOmnichainMessenger} from "./interfaces/IOmnichainMessenger.sol"; import {IOrderBook} from "./interfaces/IOrderBook.sol"; import {IPhutureOnConsumeCallback} from "./interfaces/IPhutureOnConsumeCallback.sol"; import {IStargateReceiver} from "./interfaces/stargate/IStargateReceiver.sol"; import {IStargateRouter} from "./interfaces/stargate/IStargateRouter.sol"; import {IStargateFactory} from "./interfaces/stargate/IStargateFactory.sol"; import {IStargatePool} from "./interfaces/stargate/IStargatePool.sol"; import {IEscrowDeployer} from "./escrow/interfaces/IEscrowDeployer.sol"; import {IVault} from "./interfaces/IVault.sol"; import {Currency, CurrencyLib} from "./libraries/CurrencyLib.sol"; import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol"; import {OrderLib} from "./libraries/OrderLib.sol"; import {SSTORE2} from "sstore2/SSTORE2.sol"; import {SafeCastLib} from "solmate/utils/SafeCastLib.sol"; import {BlockingApp} from "./BlockingApp.sol"; /// @title OmnichainMessenger /// @notice Base contract for cross-chain messaging and order distribution abstract contract OmnichainMessenger is BlockingApp, IStargateReceiver, IOmnichainMessenger, IPhutureOnConsumeCallback { using CurrencyLib for Currency; using FixedPointMathLib for *; using SafeCastLib for *; /// @dev Struct representing the native currency information struct NativeInfo { string name; string symbol; uint8 decimals; } /// @dev Struct for holding variables used in the `_distributeOrders` function struct DistrubuteOrdersVars { IStargateFactory factory; uint256 lzOptionsIndex; uint256 length; bytes path; } /// @dev update currencies hash on home chain uint8 internal constant REGISTER_CURRENCY = 0; /// @dev if reserve changed we only send redeemedK, recipient and owner to each remote chain uint8 internal constant TRANSFER_SNAPSHOT = 1; /// @dev once snapshot is transferred to user trading module, /// trade batches are sent to each remote chain to swap tokens and send them to home uint8 internal constant TRADE_SNAPSHOT = 2; /// @dev in the best-case scenario, we send both bodies in one message uint8 internal constant TRANSFER_AND_TRADE_SNAPSHOT = 3; /// @dev do vault withdrawals, place local orders & increment incoming orders counter by N uint8 internal constant START_REBALANCING = 4; /// @dev increment incoming orders counter by N uint8 internal constant START_RESERVE_REBALANCING = 5; /// @dev append builder with remote chain state uint8 internal constant FINISH_REBALANCING = 6; /// @dev remove dust orders which can't be sent via Stargate uint8 internal constant REMOVE_DUST_ORDERS = 7; /// @dev Native currency information NativeInfo internal nativeInfo; /// @dev Address of the Stargate composer contract address internal immutable stargateComposer; /// @dev Address of the sgETH contract address internal immutable sgETH; /// @dev Pointer to the bridging info data stored using SSTORE2 address internal bridgingInfoDataPointer; /// @dev Home chain endpoint ID uint16 internal immutable homeEid; /// @dev Address of the OrderBook contract IOrderBook internal orderBook; /// @dev Address of the EscrowDeployer contract IEscrowDeployer internal escrowDeployer; /// @dev Mapping of chain IDs to order hashes mapping(uint256 chainid => bytes32 orderHash) internal ordersHashOf; /// @notice Event emitted when outgoing orders are distributed /// @param orders The bought orders /// @param totalBought The total amount bought event OutgoingOrders(IOrderBook.BoughtOrder[] orders, uint256 totalBought); /// @notice Event emitted when the orders hash for a chain is cleared /// @param chainId The ID of the chain event OrdersHashClear(uint256 chainId); /// @notice Thrown when bridging currency is not found for a destination chain /// @param dstChainId The destination chain ID error BridgingCurrencyNotFound(uint256 dstChainId); /// @notice Thrown when the caller is not allowed to perform the action error Forbidden(); /// @notice Thrown when a query fails error QueryFailed(); /// @notice Thrown when the order hash doesn't match the expected value error OrderHashMismatch(); /// @notice Thrown when trying to set EscrowDeployer with invalid messenger error Invalid(); /// @notice Thrown when trying to set EscrowDeployer after it has been set error Set(); constructor( address owner, address _stargateComposer, address payable _endpoint, uint16 _homeEid, address _sgETH, NativeInfo memory _nativeInfo ) BlockingApp(owner, _endpoint) { stargateComposer = _stargateComposer; homeEid = _homeEid; sgETH = _sgETH; nativeInfo = _nativeInfo; } /// @notice Callback function for handling consume currency from Vault /// @param data The data passed from the Vault function phutureOnConsumeCallbackV1(bytes calldata data) external {} /// @notice Sets the address of the EscrowDeployer contract /// @param _escrowDeployer The address of the EscrowDeployer contract function setEscrowDeployer(address _escrowDeployer) external onlyOwner { // prevents setting new EscrowDeployer to protect users' access to escrow if (address(escrowDeployer) != address(0)) revert Set(); if (IEscrowDeployer(_escrowDeployer).messenger() != address(this)) revert Invalid(); escrowDeployer = IEscrowDeployer(_escrowDeployer); } /// @notice Sets the address of the OrderBook contract /// @param _orderBook The address of the OrderBook contract function setOrderBook(address _orderBook) external onlyOwner { orderBook = IOrderBook(_orderBook); } /// @notice Sets the bridging info data /// @param _infos The array of BridgingInfo structs function setBridgingInfo(BridgingInfo[] calldata _infos) external onlyOwner { bridgingInfoDataPointer = SSTORE2.write(abi.encode(_infos)); } /// @notice Withdraws the specified amount of currency to the given address /// /// @param currency The currency to withdraw /// @param to The recipient address /// @param amount The amount to withdraw function withdrawCurrency(Currency currency, address to, uint256 amount) external onlyOwner { currency.transfer(to, amount); } /// @notice Receives tokens from Stargate /// /// @param srcEid The source endpoint ID /// @param srcAddress The source address /// @param token The address of the token received /// @param amountLD The amount received in local decimals /// @param payload Additional data passed with the transfer function sgReceive( uint16 srcEid, bytes calldata srcAddress, uint256, address token, uint256 amountLD, bytes calldata payload ) external { if (!(msg.sender == stargateComposer || msg.sender == allowedCaller)) revert Forbidden(); if (keccak256(abi.encodePacked(srcAddress, address(this))) != keccak256(trustedRemotes[srcEid])) return; Currency currency = token == sgETH ? CurrencyLib.NATIVE : Currency.wrap(token); (bytes32 ordersHash, uint256 chainId) = abi.decode(payload, (bytes32, uint256)); ordersHashOf[chainId] = keccak256(abi.encode(ordersHash, currency, amountLD)); currency.transfer(address(orderBook), amountLD); } /// @notice Pushes the incoming orders to the OrderBook contract /// /// @param srcChainId The source chain ID /// @param boughtOrders The array of bought orders /// @param boughtOrdersTotalAmount The total amount of bought orders /// @param currency The currency of the bought orders /// @param receivedAmount The amount received from Stargate function pushIncomingOrders( uint256 srcChainId, IOrderBook.BoughtOrder[] calldata boughtOrders, uint256 boughtOrdersTotalAmount, Currency currency, uint256 receivedAmount ) external { if ( keccak256( abi.encode(keccak256(abi.encode(boughtOrders, boughtOrdersTotalAmount)), currency, receivedAmount) ) != ordersHashOf[srcChainId] ) revert OrderHashMismatch(); delete ordersHashOf[srcChainId]; emit OrdersHashClear(srcChainId); OrderLib.Order[] memory orders = new OrderLib.Order[](boughtOrders.length); uint256 lastIndex = boughtOrders.length - 1; uint256 utilized; for (uint256 i; i <= lastIndex; i++) { uint96 sellAmount = i == lastIndex ? (receivedAmount - utilized).safeCastTo96() : boughtOrders[i].amount.mulDivDown(receivedAmount, boughtOrdersTotalAmount).safeCastTo96(); orders[i] = OrderLib.Order({ sellAmount: sellAmount, idParams: OrderLib.OrderId({ sellCurrency: currency, localBuyCurrency: boughtOrders[i].buyCurrency, finalDestinationBuyCurrency: boughtOrders[i].buyCurrency, finalDestinationChainId: block.chainid }) }); unchecked { utilized += sellAmount; } } orderBook.receiveIncomingOrders(orders, currency, receivedAmount); } function getBridgingInfo() external view returns (BridgingInfo[] memory) { return abi.decode(SSTORE2.read(bridgingInfoDataPointer), (BridgingInfo[])); } /// @dev Distributes the pending orders to remote chains using Stargate /// @param pendingOrders The array of pending orders /// @param sgParams The array of Stargate parameters /// @param lzParams The LayerZero parameters function _distributeOrders( IOrderBook.PendingOrder[] memory pendingOrders, SgParams[] calldata sgParams, LzParams calldata lzParams ) internal { DistrubuteOrdersVars memory vars; vars.factory = IStargateFactory(IStargateRouter(stargateComposer).factory()); vars.length = pendingOrders.length; for (uint256 i; i < vars.length; ++i) { IOrderBook.PendingOrder memory pendingOrder = pendingOrders[i]; uint16 dstEid = eIds[pendingOrder.chainId]; vars.path = _getPathOrRevert(dstEid); PoolIds memory sgPoolIds = poolIds[pendingOrder.chainId]; if (pendingOrder.totalBought >= IStargatePool(vars.factory.getPool(sgPoolIds.src)).convertRate()) { SgParams calldata sgParam = sgParams[i - vars.lzOptionsIndex]; emit OutgoingOrders(pendingOrder.orders, pendingOrder.totalBought); bytes memory payload = abi.encode(keccak256(abi.encode(pendingOrder.orders, pendingOrder.totalBought)), block.chainid); bytes memory to = bytes.concat(bytes20(vars.path)); (uint256 sgMessageFee,) = IStargateRouter(stargateComposer).quoteLayerZeroFee(dstEid, 1, to, payload, sgParam.lzTxObj); if (pendingOrder.currency.isNative()) sgMessageFee += pendingOrder.totalBought; pendingOrder.currency.approve(stargateComposer, pendingOrder.totalBought); IStargateRouter(stargateComposer).swap{value: sgMessageFee}( dstEid, sgPoolIds.src, sgPoolIds.dst, payable(address(this)), pendingOrder.totalBought, sgParam.minAmountLD, sgParam.lzTxObj, to, payload ); pendingOrder.currency.approve(stargateComposer, 0); } else { _lzSend( dstEid, vars.path, abi.encode(REMOVE_DUST_ORDERS, pendingOrder.orders.length), payable(address(this)), lzParams.zroPaymentAddress, lzParams.options[vars.lzOptionsIndex++] ); } } } /// @dev Injects the local buy currency into the orders based on the bridging info /// /// @param orders The array of orders function _injectLocalBuyCurrency(OrderLib.Order[] memory orders) internal view { BridgingInfo[] memory bridgingInfo = abi.decode(SSTORE2.read(bridgingInfoDataPointer), (BridgingInfo[])); for (uint256 i; i < orders.length; ++i) { uint256 finalDestinationChainId = orders[i].idParams.finalDestinationChainId; if (finalDestinationChainId != block.chainid) { bool bridgingCurrencyFound; for (uint256 j; j < bridgingInfo.length; ++j) { if (finalDestinationChainId == bridgingInfo[j].finalDstChainId) { bridgingCurrencyFound = true; orders[i].idParams.localBuyCurrency = bridgingInfo[j].localCurrency; break; } } if (!bridgingCurrencyFound) revert BridgingCurrencyNotFound(finalDestinationChainId); } } } /// @dev Fills the metadata for registered currencies /// /// @param info The RegisterCurrenciesResult from the Vault contract /// /// @return result The filled RegisteredMetadata struct function _fillCurrenciesMetadata(IVault.RegisterCurrenciesResult calldata info) internal view returns (ICurrencyMetadata.RegisteredMetadata memory result) { result.currenciesHash = info.currenciesHash; result.chainId = block.chainid; result.metadata = new ICurrencyMetadata.CurrencyMetadata[](info.currencies.length); for (uint256 i; i < info.currencies.length; ++i) { Currency currency = info.currencies[i]; if (currency.isNative()) { NativeInfo memory _info = nativeInfo; result.metadata[i] = ICurrencyMetadata.CurrencyMetadata(_info.name, _info.symbol, _info.decimals, currency); } else { result.metadata[i] = ICurrencyMetadata.CurrencyMetadata( _queryStringOrBytes32(Currency.unwrap(currency), IERC20Metadata.name.selector), _queryStringOrBytes32(Currency.unwrap(currency), IERC20Metadata.symbol.selector), IERC20Metadata(Currency.unwrap(currency)).decimals(), currency ); } } } /// @dev Queries a string or bytes32 value from a target contract /// /// @param target The address of the target contract /// @param selector The function selector to call /// /// @return s The queried string value function _queryStringOrBytes32(address target, bytes4 selector) internal view returns (string memory s) { (bool success, bytes memory returndata) = target.staticcall(abi.encodeWithSelector(selector)); if (!success) revert QueryFailed(); if (returndata.length != 32) return abi.decode(returndata, (string)); s = string(returndata); // Find last non-zero byte uint256 length = 32; for (; length != 0; length--) { if (returndata[length - 1] != 0) break; } // Shorten length of string assembly { mstore(s, length) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.23; import {IERC20, SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; type Currency is address; using {eq as ==, neq as !=} for Currency global; function eq(Currency currency, Currency other) pure returns (bool) { return Currency.unwrap(currency) == Currency.unwrap(other); } function neq(Currency currency, Currency other) pure returns (bool) { return !eq(currency, other); } /// @title CurrencyLibrary /// @dev This library allows for transferring and holding native tokens and ERC20 tokens /// @author Modified from Uniswap (https://github.com/Uniswap/v4-core/blob/main/src/types/Currency.sol) library CurrencyLib { using SafeERC20 for IERC20; using CurrencyLib for Currency; /// @dev Currency wrapper for native currency Currency public constant NATIVE = Currency.wrap(address(0)); /// @notice Thrown when a native transfer fails error NativeTransferFailed(); /// @notice Thrown when an ERC20 transfer fails error ERC20TransferFailed(); /// @notice Thrown when deposit amount exceeds current balance error AmountExceedsBalance(); /// @notice Transfers currency /// /// @param currency Currency to transfer /// @param to Address of recipient /// @param amount Currency amount ot transfer function transfer(Currency currency, address to, uint256 amount) internal { if (amount == 0) return; // implementation from // https://github.com/transmissions11/solmate/blob/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/SafeTransferLib.sol bool success; if (currency.isNative()) { assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } if (!success) revert NativeTransferFailed(); } else { assembly { // We'll write our calldata to this slot below, but restore it later. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because that's the total length of our calldata (4 + 32 * 2) // Counterintuitively, this call() must be positioned after the or() in the // surrounding and() because and() evaluates its arguments from right to left. call(gas(), currency, 0, freeMemoryPointer, 68, 0, 32) ) } if (!success) revert ERC20TransferFailed(); } } /// @notice Approves currency /// /// @param currency Currency to approve /// @param spender Address of spender /// @param amount Currency amount to approve function approve(Currency currency, address spender, uint256 amount) internal { if (isNative(currency)) return; IERC20(Currency.unwrap(currency)).forceApprove(spender, amount); } /// @notice Returns the balance of a given currency for a specific account /// /// @param currency The currency to check /// @param account The address of the account /// /// @return The balance of the specified currency for the given account function balanceOf(Currency currency, address account) internal view returns (uint256) { return currency.isNative() ? account.balance : IERC20(Currency.unwrap(currency)).balanceOf(account); } /// @notice Returns the balance of a given currency for this contract /// /// @param currency The currency to check /// /// @return The balance of the specified currency for this contract function balanceOfSelf(Currency currency) internal view returns (uint256) { return currency.isNative() ? address(this).balance : IERC20(Currency.unwrap(currency)).balanceOf(address(this)); } /// @notice Checks if the specified currency is the native currency /// /// @param currency The currency to check /// /// @return `true` if the specified currency is the native currency, `false` otherwise function isNative(Currency currency) internal pure returns (bool) { return currency == NATIVE; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; import {IOrderBook} from "./IOrderBook.sol"; import {IVault} from "./IVault.sol"; import {IStargateRouter} from "./stargate/IStargateRouter.sol"; import {Currency} from "../libraries/CurrencyLib.sol"; interface IOmnichainMessenger { struct BridgingInfo { uint256 finalDstChainId; Currency localCurrency; } struct HashedResult { uint256 chainId; bytes32 hash; } struct LzParams { bytes[] options; address zroPaymentAddress; } struct SgParams { IStargateRouter.lzTxObj lzTxObj; uint256 minAmountLD; } function withdrawCurrency(Currency currency, address to, uint256 amount) external; function setOrderBook(address orderBook) external; function setEscrowDeployer(address escrowDeployer) external; function setBridgingInfo(BridgingInfo[] calldata _infos) external; function pushIncomingOrders( uint256 srcChainId, IOrderBook.BoughtOrder[] memory boughtOrders, uint256 boughtOrdersTotalAmount, Currency currency, uint256 receivedAmount ) external; function finishVaultRebalancing( IOrderBook.FinishOrderExecutionParams calldata orderBookParams, IVault.EndRebalancingParams calldata params, SgParams[] calldata sgParams, LzParams calldata lzParams, address payable refundAddress ) external payable; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import {Currency} from "../libraries/CurrencyLib.sol"; type a160u96 is uint256; using {addr, unpack, unpackRaw, currency, value, eq as ==, neq as !=} for a160u96 global; error AddressMismatch(address, address); function neq(a160u96 a, a160u96 b) pure returns (bool) { return !eq(a, b); } function eq(a160u96 a, a160u96 b) pure returns (bool) { return a160u96.unwrap(a) == a160u96.unwrap(b); } function currency(a160u96 packed) pure returns (Currency) { return Currency.wrap(addr(packed)); } function addr(a160u96 packed) pure returns (address) { return address(uint160(a160u96.unwrap(packed))); } function value(a160u96 packed) pure returns (uint96) { return uint96(a160u96.unwrap(packed) >> 160); } function unpack(a160u96 packed) pure returns (Currency _curr, uint96 _value) { uint256 raw = a160u96.unwrap(packed); _curr = Currency.wrap(address(uint160(raw))); _value = uint96(raw >> 160); } function unpackRaw(a160u96 packed) pure returns (address _addr, uint96 _value) { uint256 raw = a160u96.unwrap(packed); _addr = address(uint160(raw)); _value = uint96(raw >> 160); } library A160U96Factory { function create(address _addr, uint96 _value) internal pure returns (a160u96) { return a160u96.wrap((uint256(_value) << 160) | uint256(uint160(_addr))); } function create(Currency _currency, uint96 _value) internal pure returns (a160u96) { return create(Currency.unwrap(_currency), _value); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Safe unsigned integer casting library that reverts on overflow. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeCastLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol) library SafeCastLib { function safeCastTo248(uint256 x) internal pure returns (uint248 y) { require(x < 1 << 248); y = uint248(x); } function safeCastTo240(uint256 x) internal pure returns (uint240 y) { require(x < 1 << 240); y = uint240(x); } function safeCastTo232(uint256 x) internal pure returns (uint232 y) { require(x < 1 << 232); y = uint232(x); } function safeCastTo224(uint256 x) internal pure returns (uint224 y) { require(x < 1 << 224); y = uint224(x); } function safeCastTo216(uint256 x) internal pure returns (uint216 y) { require(x < 1 << 216); y = uint216(x); } function safeCastTo208(uint256 x) internal pure returns (uint208 y) { require(x < 1 << 208); y = uint208(x); } function safeCastTo200(uint256 x) internal pure returns (uint200 y) { require(x < 1 << 200); y = uint200(x); } function safeCastTo192(uint256 x) internal pure returns (uint192 y) { require(x < 1 << 192); y = uint192(x); } function safeCastTo184(uint256 x) internal pure returns (uint184 y) { require(x < 1 << 184); y = uint184(x); } function safeCastTo176(uint256 x) internal pure returns (uint176 y) { require(x < 1 << 176); y = uint176(x); } function safeCastTo168(uint256 x) internal pure returns (uint168 y) { require(x < 1 << 168); y = uint168(x); } function safeCastTo160(uint256 x) internal pure returns (uint160 y) { require(x < 1 << 160); y = uint160(x); } function safeCastTo152(uint256 x) internal pure returns (uint152 y) { require(x < 1 << 152); y = uint152(x); } function safeCastTo144(uint256 x) internal pure returns (uint144 y) { require(x < 1 << 144); y = uint144(x); } function safeCastTo136(uint256 x) internal pure returns (uint136 y) { require(x < 1 << 136); y = uint136(x); } function safeCastTo128(uint256 x) internal pure returns (uint128 y) { require(x < 1 << 128); y = uint128(x); } function safeCastTo120(uint256 x) internal pure returns (uint120 y) { require(x < 1 << 120); y = uint120(x); } function safeCastTo112(uint256 x) internal pure returns (uint112 y) { require(x < 1 << 112); y = uint112(x); } function safeCastTo104(uint256 x) internal pure returns (uint104 y) { require(x < 1 << 104); y = uint104(x); } function safeCastTo96(uint256 x) internal pure returns (uint96 y) { require(x < 1 << 96); y = uint96(x); } function safeCastTo88(uint256 x) internal pure returns (uint88 y) { require(x < 1 << 88); y = uint88(x); } function safeCastTo80(uint256 x) internal pure returns (uint80 y) { require(x < 1 << 80); y = uint80(x); } function safeCastTo72(uint256 x) internal pure returns (uint72 y) { require(x < 1 << 72); y = uint72(x); } function safeCastTo64(uint256 x) internal pure returns (uint64 y) { require(x < 1 << 64); y = uint64(x); } function safeCastTo56(uint256 x) internal pure returns (uint56 y) { require(x < 1 << 56); y = uint56(x); } function safeCastTo48(uint256 x) internal pure returns (uint48 y) { require(x < 1 << 48); y = uint48(x); } function safeCastTo40(uint256 x) internal pure returns (uint40 y) { require(x < 1 << 40); y = uint40(x); } function safeCastTo32(uint256 x) internal pure returns (uint32 y) { require(x < 1 << 32); y = uint32(x); } function safeCastTo24(uint256 x) internal pure returns (uint24 y) { require(x < 1 << 24); y = uint24(x); } function safeCastTo16(uint256 x) internal pure returns (uint16 y) { require(x < 1 << 16); y = uint16(x); } function safeCastTo8(uint256 x) internal pure returns (uint8 y) { require(x < 1 << 8); y = uint8(x); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; /// @title BitSet /// @notice A library for managing bitsets library BitSet { uint256 private constant WORD_SHIFT = 8; /// @notice Checks if the next bit is set in the given word starting from the given bit position /// /// @param word The word to check /// @param bit The bit position /// /// @return r True if the next bit is set, false otherwise function hasNext(uint256 word, uint256 bit) internal pure returns (bool r) { assembly ("memory-safe") { r := and(shr(bit, word), 1) } } /// @notice Finds the position of the next set bit in the given word starting from the given bit position /// /// @dev This function uses a lookup table approach to find the position of the next set bit. /// It first shifts the word right by the given bit position and then checks the lower 3 bits /// of the resulting word to determine the position of the next set bit. /// If no set bit is found, it returns 256 to indicate that there are no more set bits. /// /// @param word The word to search /// @param b The starting bit position /// /// @return nb The position of the next set bit function find(uint256 word, uint256 b) internal pure returns (uint256 nb) { assembly ("memory-safe") { let w := shr(b, word) switch w case 0 { // no more bits nb := 256 } default { // 0b000 = 0 // 0b001 = 1 // 0b010 = 2 // 0b011 = 3 // 0b100 = 4 // 0b101 = 5 // 0b110 = 6 // 0b111 = 7 switch and(w, 7) case 0 { nb := add(lsb(w), b) } case 2 { nb := add(b, 1) } case 4 { nb := add(b, 2) } case 6 { nb := add(b, 1) } default { nb := b } } function lsb(x) -> r { if iszero(x) { revert(0, 0) } r := 255 switch gt(and(x, 0xffffffffffffffffffffffffffffffff), 0) case 1 { r := sub(r, 128) } case 0 { x := shr(128, x) } switch gt(and(x, 0xffffffffffffffff), 0) case 1 { r := sub(r, 64) } case 0 { x := shr(64, x) } switch gt(and(x, 0xffffffff), 0) case 1 { r := sub(r, 32) } case 0 { x := shr(32, x) } switch gt(and(x, 0xffff), 0) case 1 { r := sub(r, 16) } case 0 { x := shr(16, x) } switch gt(and(x, 0xff), 0) case 1 { r := sub(r, 8) } case 0 { x := shr(8, x) } switch gt(and(x, 0xf), 0) case 1 { r := sub(r, 4) } case 0 { x := shr(4, x) } switch gt(and(x, 0x3), 0) case 1 { r := sub(r, 2) } case 0 { x := shr(2, x) } switch gt(and(x, 0x1), 0) case 1 { r := sub(r, 1) } } } } /// @notice Computes the value at the given word index and bit position /// /// @param wordIndex The index of the word /// @param bit The bit position within the word /// /// @return r The computed value function valueAt(uint256 wordIndex, uint256 bit) internal pure returns (uint256 r) { assembly ("memory-safe") { r := or(shl(8, wordIndex), bit) } } /// @notice Creates a new bitset with the given maximum size /// /// @param maxSize The maximum size of the bitset /// /// @return bitset The created bitset function create(uint256 maxSize) internal pure returns (uint256[] memory bitset) { bitset = new uint256[](_capacity(maxSize)); } /// @notice Checks if the given value is contained in the bitset /// /// @param bitset The bitset to check /// @param value The value to search for /// /// @return _contains True if the value is contained in the bitset, false otherwise function contains(uint256[] memory bitset, uint256 value) internal pure returns (bool _contains) { (uint256 wordIndex, uint8 bit) = _bitOffset(value); if (wordIndex < bitset.length) { _contains = (bitset[wordIndex] & (1 << bit)) != 0; } } /// @notice Adds the given value to the bitset /// /// @param bitset The bitset to modify /// @param value The value to add /// /// @return The modified bitset function add(uint256[] memory bitset, uint256 value) internal pure returns (uint256[] memory) { (uint256 wordIndex, uint8 bit) = _bitOffset(value); bitset[wordIndex] |= (1 << bit); return bitset; } /// @notice Adds all elements from bitset b to bitset a /// /// @param a The destination bitset /// @param b The source bitset /// /// @return c The resulting bitset function addAll(uint256[] memory a, uint256[] memory b) internal pure returns (uint256[] memory c) { (uint256 min, uint256 max) = a.length < b.length ? (a.length, b.length) : (b.length, a.length); c = new uint256[](max); uint256 i; for (; i < min; ++i) { c[i] = a[i] | b[i]; } // copy leftover elements from a for (; i < a.length; ++i) { c[i] = a[i]; } // copy leftover elements from b for (; i < b.length; ++i) { c[i] = b[i]; } } /// @notice Removes the given value from the bitset /// /// @param bitset The bitset to modify /// @param value The value to remove /// /// @return The modified bitset function remove(uint256[] memory bitset, uint256 value) internal pure returns (uint256[] memory) { (uint256 wordIndex, uint8 bit) = _bitOffset(value); bitset[wordIndex] &= ~(1 << bit); return bitset; } /// @notice Computes the size (number of set bits) of the bitset /// /// @param bitset The bitset to compute the size of /// /// @return count The number of set bits in the bitset function size(uint256[] memory bitset) internal pure returns (uint256 count) { for (uint256 i; i < bitset.length; ++i) { count += _countSetBits(bitset[i]); } } /// @dev Computes the word index and bit position for the given value /// /// @param value The value to compute the offsets for /// /// @return wordIndex The index of the word containing the value /// @return bit The bit position within the word function _bitOffset(uint256 value) private pure returns (uint256 wordIndex, uint8 bit) { assembly ("memory-safe") { wordIndex := shr(8, value) // mask bits that don't fit the first wordIndex's bits // n % 2^i = n & (2^i - 1) bit := and(value, 255) } } /// @dev Computes the number of words required to store the given maximum size /// /// @param maxSize The maximum size of the bitset /// /// @return words The number of words required function _capacity(uint256 maxSize) private pure returns (uint256 words) { // round up words = (maxSize + type(uint8).max) >> WORD_SHIFT; } /// @dev Counts the number of set bits in the given word using Brian Kernighan's algorithm /// /// @param x The word to count the set bits of /// /// @return count The number of set bits in the word function _countSetBits(uint256 x) private pure returns (uint256 count) { // Brian Kernighan's Algorithm // This algorithm counts the number of set bits in a word by repeatedly // clearing the least significant set bit until the word becomes zero. while (x != 0) { unchecked { // cannot overflow, x > 0 x = x & (x - 1); ++count; } } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) /// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) library FixedPointMathLib { /*////////////////////////////////////////////////////////////// SIMPLIFIED FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ uint256 internal constant MAX_UINT256 = 2**256 - 1; uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s. function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. } function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up. } function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down. } function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. } /*////////////////////////////////////////////////////////////// LOW LEVEL FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ function mulDivDown( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) { revert(0, 0) } // Divide x * y by the denominator. z := div(mul(x, y), denominator) } } function mulDivUp( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) { revert(0, 0) } // If x * y modulo the denominator is strictly greater than 0, // 1 is added to round up the division of x * y by the denominator. z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator)) } } function rpow( uint256 x, uint256 n, uint256 scalar ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { switch x case 0 { switch n case 0 { // 0 ** 0 = 1 z := scalar } default { // 0 ** n = 0 z := 0 } } default { switch mod(n, 2) case 0 { // If n is even, store scalar in z for now. z := scalar } default { // If n is odd, store x in z for now. z := x } // Shifting right by 1 is like dividing by 2. let half := shr(1, scalar) for { // Shift n right by 1 before looping to halve it. n := shr(1, n) } n { // Shift n right by 1 each iteration to halve it. n := shr(1, n) } { // Revert immediately if x ** 2 would overflow. // Equivalent to iszero(eq(div(xx, x), x)) here. if shr(128, x) { revert(0, 0) } // Store x squared. let xx := mul(x, x) // Round to the nearest number. let xxRound := add(xx, half) // Revert if xx + half overflowed. if lt(xxRound, xx) { revert(0, 0) } // Set x to scaled xxRound. x := div(xxRound, scalar) // If n is even: if mod(n, 2) { // Compute z * x. let zx := mul(z, x) // If z * x overflowed: if iszero(eq(div(zx, x), z)) { // Revert if x is non-zero. if iszero(iszero(x)) { revert(0, 0) } } // Round to the nearest number. let zxRound := add(zx, half) // Revert if zx + half overflowed. if lt(zxRound, zx) { revert(0, 0) } // Return properly scaled zxRound. z := div(zxRound, scalar) } } } } } /*////////////////////////////////////////////////////////////// GENERAL NUMBER UTILITIES //////////////////////////////////////////////////////////////*/ function sqrt(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { let y := x // We start y at x, which will help us make our initial estimate. z := 181 // The "correct" value is 1, but this saves a multiplication later. // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. // We check y >= 2^(k + 8) but shift right by k bits // each branch to ensure that if x >= 256, then y >= 256. if iszero(lt(y, 0x10000000000000000000000000000000000)) { y := shr(128, y) z := shl(64, z) } if iszero(lt(y, 0x1000000000000000000)) { y := shr(64, y) z := shl(32, z) } if iszero(lt(y, 0x10000000000)) { y := shr(32, y) z := shl(16, z) } if iszero(lt(y, 0x1000000)) { y := shr(16, y) z := shl(8, z) } // Goal was to get z*z*y within a small factor of x. More iterations could // get y in a tighter range. Currently, we will have y in [256, 256*2^16). // We ensured y >= 256 so that the relative difference between y and y+1 is small. // That's not possible if x < 256 but we can just verify those cases exhaustively. // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256. // Correctness can be checked exhaustively for x < 256, so we assume y >= 256. // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps. // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256. // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18. // There is no overflow risk here since y < 2^136 after the first branch above. z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181. // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // If x+1 is a perfect square, the Babylonian method cycles between // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case. // If you don't care whether the floor or ceil square root is returned, you can remove this statement. z := sub(z, lt(div(x, z), z)) } } function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Mod x by y. Note this will return // 0 instead of reverting if y is zero. z := mod(x, y) } } function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { // Divide x by y. Note this will return // 0 instead of reverting if y is zero. r := div(x, y) } } function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Add 1 to x * y if x % y > 0. Note this will // return 0 instead of reverting if y is zero. z := add(gt(mod(x, y), 0), div(x, y)) } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol"; /// @title PriceLib /// @notice A library for handling fixed-point arithmetic for prices library PriceLib { using FixedPointMathLib for uint256; /// @dev 2**128 uint256 internal constant Q128 = 0x100000000000000000000000000000000; uint16 internal constant PRICE_ORACLE_DECIMALS = 18; uint256 internal constant DECIMALS_MULTIPLIER = 10 ** PRICE_ORACLE_DECIMALS; /// @notice Converts (down) an amount in base units to an amount in asset units based on a fixed-price value /// @param base The amount to convert in base units /// @param price The fixed-price value represented as a uint256 /// @return The equivalent amount in asset units function convertToAssetsDown(uint256 base, uint256 price) internal pure returns (uint256) { return base.mulDivDown(price, Q128); } /// @notice Converts (up) an amount in base units to an amount in asset units based on a fixed-price value /// @param base The amount to convert in base units /// @param price The fixed-price value represented as a uint256 /// @return The equivalent amount in asset units function convertToAssetsUp(uint256 base, uint256 price) internal pure returns (uint256) { return base.mulDivUp(price, Q128); } /// @notice Converts (down) an amount in asset units to an amount in base units based on a fixed-price value /// @param assets The amount to convert in asset units /// @param price The fixed-price value represented as a uint256 /// @return The equivalent amount in base units function convertToBaseDown(uint256 assets, uint256 price) internal pure returns (uint256) { return assets.mulDivDown(Q128, price); } /// @notice Converts (up) an amount in asset units to an amount in base units based on a fixed-price value /// @param assets The amount to convert in asset units /// @param price The fixed-price value represented as a uint256 /// @return The equivalent amount in base units function convertToBaseUp(uint256 assets, uint256 price) internal pure returns (uint256) { return assets.mulDivUp(Q128, price); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import {Currency} from "./CurrencyLib.sol"; /// @title StackLib /// @notice A library for managing a stack data library StackLib { /// @dev Represents the data held in each stack node struct Data { // Index of order uint256 orderIndex; // Currency of order Currency currency; // Amount of order uint256 delta; // `price` for sell, `chainId` for buy uint256 data; // Available asset for sell data, 0 for buy data uint256 availableAssets; } /// @dev Represents a node in the stack struct Node { // Pointer to the next node uint256 next; // Value of the node Data value; } /// @notice Pushes a new sell order onto the stack /// /// @param head The current head of the stack /// @param delta The delta value of the order /// @param availableAssets The number of assets available for selling /// @param orderIndex The index of the order /// @param currency The currency used in the order /// @param price The price of the assets in the order /// /// @return newNode The new node created with the given data function push( Node memory head, uint256 delta, uint256 availableAssets, uint256 orderIndex, Currency currency, uint256 price ) internal pure returns (Node memory newNode) { newNode.value = Data(orderIndex, currency, delta, price, availableAssets); assembly { // Store the address of the current head in the new node's 'next' mstore(newNode, head) } } /// @notice Pushes a new buy order onto the stack /// /// @param head The current head of the stack /// @param delta The delta value of the order /// @param orderIndex The index of the order /// @param currency The currency used in the order /// @param chainId The chain ID associated with the buy order /// /// @return newNode The new node created with the given data function push(Node memory head, uint256 delta, uint256 orderIndex, Currency currency, uint256 chainId) internal pure returns (Node memory newNode) { newNode.value = Data(orderIndex, currency, delta, chainId, 0); assembly { // Store the address of the current head in the new node's 'next' mstore(newNode, head) } } /// @notice Pops the top value from the stack /// /// @param head The current head of the stack /// /// @return nextNode The next node in the stack after popping function pop(Node memory head) internal pure returns (Node memory nextNode) { assembly { // Load the address of the next node (which head points to) nextNode := mload(head) } } /// @notice Checks if the stack is not empty /// /// @param head The head of the stack to check /// /// @return `true` if the stack is not empty, `false` otherwise function notEmpty(Node memory head) internal pure returns (bool) { return head.next != 0 || head.value.delta != 0; } /// @notice Retrieves the value of the top node of the stack /// /// @param head The head of the stack /// /// @return The data value of the top node of the stack function peek(Node memory head) internal pure returns (Data memory) { return head.value; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; import {IIndex} from "./IIndex.sol"; import {IVault} from "./IVault.sol"; import {ICurrencyMetadata} from "./ICurrencyMetadata.sol"; import {Currency} from "../libraries/CurrencyLib.sol"; interface IConfigBuilder { struct Anatomy { uint256[] chainIdSet; uint256[][] currencyIdSets; } struct SharedConfig { uint256 AUMDilutionPerSecond; bool useCustomAUMFee; address metadata; } struct FeeConfig { uint16 BPs; bool useCustomCallback; } struct Config { SharedConfig shared; FeeConfig depositFee; FeeConfig redemptionFee; } struct StartReserveRebalancingParams { Anatomy anatomy; uint256[] chainIds; Currency[][] currencies; } struct StartRebalancingParams { Anatomy anatomy; Anatomy newAnatomy; uint256[] chainIds; Currency[][] currencies; uint256[] newWeights; uint256[] orderCounts; // count of orders for current anatomy chains bytes payload; } function startRebalancing(StartRebalancingParams calldata params, bytes calldata data) external payable; function startReserveRebalancing(StartReserveRebalancingParams calldata params, bytes calldata data) external payable; function finishRebalancing(IVault.RebalancingResult[] calldata results, IConfigBuilder.Config calldata config) external returns (IIndex.DepositConfig memory deposit, IIndex.RedemptionConfig memory redemption); function chainRebalancingFinished(uint256 chainId, bytes32 resultHash) external; function currenciesUpdated(ICurrencyMetadata.RegisteredMetadata calldata result) external; function registerChain(uint256 chainId) external; function setMessenger(address _messenger) external; function setConfig(IConfigBuilder.Config memory _config) external returns (IIndex.DepositConfig memory deposit, IIndex.RedemptionConfig memory redemption); function configs(Config calldata _config) external view returns (IIndex.DepositConfig memory deposit, IIndex.RedemptionConfig memory redemption); function configHash() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; import {Currency} from "../libraries/CurrencyLib.sol"; interface ICurrencyMetadata { struct RegisteredMetadata { uint256 chainId; CurrencyMetadata[] metadata; bytes32 currenciesHash; } struct CurrencyMetadata { string name; string symbol; uint8 decimals; Currency currency; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; interface IPhutureOnConsumeCallback { function phutureOnConsumeCallbackV1(bytes calldata data) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; interface IStargateReceiver { function sgReceive( uint16 _eid, bytes memory _srcAddress, uint256 _nonce, address _token, uint256 amountLD, bytes memory payload ) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; interface IStargateRouter { struct lzTxObj { uint256 dstGasForCall; // extra gas, if calling smart contract, uint256 dstNativeAmount; // amount of dust dropped in destination wallet bytes dstNativeAddr; // destination wallet for dust } function swap( uint16 _dstEid, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress, uint256 _amountLD, uint256 _minAmountLD, lzTxObj memory _lzTxParams, bytes calldata _to, bytes calldata _payload ) external payable; function quoteLayerZeroFee( uint16 _dstEid, uint8 _functionType, bytes calldata _toAddress, bytes calldata _transferAndCallPayload, lzTxObj memory _lzTxParams ) external view returns (uint256, uint256); function factory() external view returns (address); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; interface IStargateFactory { function getPool(uint256 poolId) external view returns (address); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; interface IStargatePool { function convertRate() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./utils/Bytecode.sol"; /** @title A key-value storage with auto-generated keys for storing chunks of data with a lower write & read cost. @author Agustin Aguilar <[email protected]> Readme: https://github.com/0xsequence/sstore2#readme */ library SSTORE2 { error WriteError(); /** @notice Stores `_data` and returns `pointer` as key for later retrieval @dev The pointer is a contract address with `_data` as code @param _data to be written @return pointer Pointer to the written `_data` */ function write(bytes memory _data) internal returns (address pointer) { // Append 00 to _data so contract can't be called // Build init code bytes memory code = Bytecode.creationCodeFor( abi.encodePacked( hex'00', _data ) ); // Deploy contract using create assembly { pointer := create(0, add(code, 32), mload(code)) } // Address MUST be non-zero if (pointer == address(0)) revert WriteError(); } /** @notice Reads the contents of the `_pointer` code as data, skips the first byte @dev The function is intended for reading pointers generated by `write` @param _pointer to be read @return data read from `_pointer` contract */ function read(address _pointer) internal view returns (bytes memory) { return Bytecode.codeAt(_pointer, 1, type(uint256).max); } /** @notice Reads the contents of the `_pointer` code as data, skips the first byte @dev The function is intended for reading pointers generated by `write` @param _pointer to be read @param _start number of bytes to skip @return data read from `_pointer` contract */ function read(address _pointer, uint256 _start) internal view returns (bytes memory) { return Bytecode.codeAt(_pointer, _start + 1, type(uint256).max); } /** @notice Reads the contents of the `_pointer` code as data, skips the first byte @dev The function is intended for reading pointers generated by `write` @param _pointer to be read @param _start number of bytes to skip @param _end index before which to end extraction @return data read from `_pointer` contract */ function read(address _pointer, uint256 _start, uint256 _end) internal view returns (bytes memory) { return Bytecode.codeAt(_pointer, _start + 1, _end + 1); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import {IBlockingApp} from "./interfaces/IBlockingApp.sol"; import {ILayerZeroEndpoint} from "layerzero/interfaces/ILayerZeroEndpoint.sol"; import {Owned} from "solmate/auth/Owned.sol"; /// @title BlockingApp /// @notice Abstract contract for a LayerZero blocking queue UA abstract contract BlockingApp is IBlockingApp, Owned { /// @notice The LayerZero Endpoint contract ILayerZeroEndpoint public immutable lzEndpoint; /// @notice Address whos allowed to call `lzReceive` method /// @dev this slot is used for stateOverrides during gas estimation address internal allowedCaller; /// @notice Mapping of remote chainIDs to their respective LayerZero Endpoint IDs mapping(uint256 => uint16) public eIds; /// @notice Mapping of LayerZero Endpoint IDs to their trusted remote paths mapping(uint16 => bytes) public trustedRemotes; /// @notice Mapping of remote chainIDs to their respective Stargate Pool IDs mapping(uint256 => PoolIds) public poolIds; /// @notice Mapping of LayerZero Endpoint IDs to the minimum gas amount required for the chain mapping(uint16 => uint256) public minGasAmountForChain; /// @notice Event emitted when a trusted remote is set /// /// @param remoteEid LayerZero Endpoint ID on the remote chain /// @param path Trusted path to the remote chain (abi-encoded remote address and local address) /// @param poolIds The Stargate Oool IDs associated with the trusted remote event TrustedRemoteSet(uint16 remoteEid, bytes path, PoolIds poolIds); /// @notice Thrown when the caller is not the LayerZero endpoint error OnlyEndpoint(); /// @notice Thrown if ZRO payments are not supported error ZRONotSupported(); /// @notice Thrown when a trusted remote path is not found for the given LayerZero Endpoint ID /// @param eid LayerZero Endpoint ID for which the path was not found error PathNotFound(uint16 eid); constructor(address owner, address _endpoint) Owned(owner) { lzEndpoint = ILayerZeroEndpoint(_endpoint); } receive() external payable {} /// @notice Sets the configuration for specified LayerZero Endpoint ID /// /// @param version Configuration version /// @param eid LayerZero Endpoint ID /// @param configType Configuration type /// @param config Configuration data function setConfig(uint16 version, uint16 eid, uint256 configType, bytes calldata config) external override onlyOwner { lzEndpoint.setConfig(version, eid, configType, config); } /// @notice Sets the send version for the LayerZero endpoint /// /// @param version The send version to set function setSendVersion(uint16 version) external override onlyOwner { lzEndpoint.setSendVersion(version); } /// @notice Sets the receive version for the LayerZero endpoint /// /// @param version The receive version to set function setReceiveVersion(uint16 version) external override onlyOwner { lzEndpoint.setReceiveVersion(version); } /// @notice Forces the resumption of message receiving for the specified source LayerZero Endpoint and address /// /// @param srcEid The source LayerZero Endpoint ID /// @param srcAddress The source address function forceResumeReceive(uint16 srcEid, bytes calldata srcAddress) external override onlyOwner { lzEndpoint.forceResumeReceive(srcEid, srcAddress); } /// @notice Sets the trusted remote for the specified remote chain ID /// /// @param remoteChainId The remote chain ID /// @param remoteEid The remote LayerZero Endpoint ID /// @param minGasAmount The minimum gas amount required for the remote chain /// @param path The trusted remote path (abi.encodePacked(remoteAddress, localAddress)) /// @param _poolIds The pool IDs associated with the trusted remote function setTrustedRemote( uint256 remoteChainId, uint16 remoteEid, uint256 minGasAmount, bytes calldata path, PoolIds calldata _poolIds ) external onlyOwner { eIds[remoteChainId] = remoteEid; poolIds[remoteChainId] = _poolIds; trustedRemotes[remoteEid] = path; minGasAmountForChain[remoteEid] = minGasAmount; emit TrustedRemoteSet(remoteEid, path, _poolIds); } /// @notice Receives messages from the LayerZero /// /// @param srcEid The source LayerZero Endpoint ID /// @param srcAddress The source address /// @param message The received message function lzReceive(uint16 srcEid, bytes calldata srcAddress, uint64, bytes calldata message) external override { if (!(msg.sender == address(lzEndpoint) || msg.sender == allowedCaller)) revert OnlyEndpoint(); if (keccak256(srcAddress) != keccak256(trustedRemotes[srcEid])) return; _lzReceive(message); } /// @notice Retrieves the configuration for the specified LayerZero Endpoint ID and configuration type /// /// @param version The configuration version /// @param eid The LayerZero Endpoint ID /// @param configType The configuration type /// /// @return The configuration data function getConfig(uint16 version, uint16 eid, address, uint256 configType) external view returns (bytes memory) { return lzEndpoint.getConfig(version, eid, address(this), configType); } /// @dev Sends a message through the LayerZero endpoint /// /// @param dstEid The destination LayerZero Endpoint ID /// @param path The trusted remote path /// @param message The message to send /// @param refundAddress The address to receive refunds /// @param zroPaymentAddress The address for ZRO payments /// @param options Additional options for the message function _lzSend( uint16 dstEid, bytes memory path, bytes memory message, address payable refundAddress, address zroPaymentAddress, bytes memory options ) internal { if (zroPaymentAddress != address(0)) revert ZRONotSupported(); // solhint-disable-next-line check-send-result lzEndpoint.send{value: address(this).balance}(dstEid, path, message, refundAddress, address(0), options); } /// @dev Processes messages from the LayerZero endpoint /// /// @param message The received message function _lzReceive(bytes calldata message) internal virtual; /// @dev Retrieves the trusted remote path for the specified LayerZero Endpoint ID, /// or reverts if not found /// /// @param eid The LayerZero Endpoint ID /// /// @return path The trusted remote path function _getPathOrRevert(uint16 eid) internal view returns (bytes memory path) { path = trustedRemotes[eid]; if (path.length == 0) revert PathNotFound(eid); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; import {IVault} from "./IVault.sol"; import {Currency} from "../libraries/CurrencyLib.sol"; import {a160u96} from "../utils/a160u96.sol"; interface IIndex is IVault { struct IndexState { uint128 totalSupply; uint96 fees; uint32 lastAUMAccrualTimestamp; uint96 reserve; } struct Config { uint256 latestSnapshot; // needed to get the latest k value uint256 AUMDilutionPerSecond; bool useCustomAUMFee; address staticPriceOracle; address metadata; } struct FeeConfig { uint16 BPs; bool useCustomCallback; } struct DepositConfig { Config shared; FeeConfig fee; } struct RedemptionConfig { Config shared; FeeConfig fee; address forwarder; a160u96[] homeCurrencies; // Reserve currency + Vault's currencies } struct DepositParams { DepositConfig config; address recipient; bytes payload; } struct RedemptionParams { RedemptionConfig config; address owner; uint128 shares; bytes payload; } struct RedemptionInfo { uint256 reserveValuation; uint256 totalValuation; uint256 totalReserveShares; uint128 totalSupplyAfterAUMAccrual; uint256 totalKBeforeRedeem; uint256 accountBalanceSharesBeforeRedeem; uint96 accountReserveRedeemed; uint256 accountReserveSharesRedeemed; uint256 accountKRedeemed; uint256 reservePriceInQ128; } error IndexConfigHash(); error IndexConfigMismatch(); error IndexInitialConfig(); error PermitDeadlineExpired(); error InvalidSigner(); error ZeroAddressTransfer(); error InvalidSender(); error ZeroDeposit(); function deposit(DepositParams calldata params, address cbTarget, bytes calldata cbData) external payable returns (uint256 shares); function redeem(RedemptionParams calldata params, address forwardedSender, address recipient) external returns (RedemptionInfo memory redeemed); function startIndexRebalancing() external; function setConfig( Config calldata _prevConfig, DepositConfig calldata _depositConfig, RedemptionConfig calldata _redemptionConfig ) external; function setFeePool(address feePool) external; function accrueFee(address recipient) external; function reserve() external view returns (Currency); function reserveBalance() external view returns (uint96); function kSelf() external view returns (uint256); function fees() external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library Bytecode { error InvalidCodeAtRange(uint256 _size, uint256 _start, uint256 _end); /** @notice Generate a creation code that results on a contract with `_code` as bytecode @param _code The returning value of the resulting `creationCode` @return creationCode (constructor) for new contract */ function creationCodeFor(bytes memory _code) internal pure returns (bytes memory) { /* 0x00 0x63 0x63XXXXXX PUSH4 _code.length size 0x01 0x80 0x80 DUP1 size size 0x02 0x60 0x600e PUSH1 14 14 size size 0x03 0x60 0x6000 PUSH1 00 0 14 size size 0x04 0x39 0x39 CODECOPY size 0x05 0x60 0x6000 PUSH1 00 0 size 0x06 0xf3 0xf3 RETURN <CODE> */ return abi.encodePacked( hex"63", uint32(_code.length), hex"80_60_0E_60_00_39_60_00_F3", _code ); } /** @notice Returns the size of the code on a given address @param _addr Address that may or may not contain code @return size of the code on the given `_addr` */ function codeSize(address _addr) internal view returns (uint256 size) { assembly { size := extcodesize(_addr) } } /** @notice Returns the code of a given address @dev It will fail if `_end < _start` @param _addr Address that may or may not contain code @param _start number of bytes of code to skip on read @param _end index before which to end extraction @return oCode read from `_addr` deployed bytecode Forked from: https://gist.github.com/KardanovIR/fe98661df9338c842b4a30306d507fbd */ function codeAt(address _addr, uint256 _start, uint256 _end) internal view returns (bytes memory oCode) { uint256 csize = codeSize(_addr); if (csize == 0) return bytes(""); if (_start > csize) return bytes(""); if (_end < _start) revert InvalidCodeAtRange(csize, _start, _end); unchecked { uint256 reqSize = _end - _start; uint256 maxSize = csize - _start; uint256 size = maxSize < reqSize ? maxSize : reqSize; assembly { // allocate output byte array - this could also be done without assembly // by using o_code = new bytes(size) oCode := mload(0x40) // new "memory end" including padding mstore(0x40, add(oCode, and(add(add(size, 0x20), 0x1f), not(0x1f)))) // store length in memory mstore(oCode, size) // actually retrieve the code, this needs assembly extcodecopy(_addr, add(oCode, 0x20), _start, size) } } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; import {ILayerZeroReceiver} from "layerzero/interfaces/ILayerZeroReceiver.sol"; import {ILayerZeroUserApplicationConfig} from "layerzero/interfaces/ILayerZeroUserApplicationConfig.sol"; interface IBlockingApp is ILayerZeroReceiver, ILayerZeroUserApplicationConfig { struct PoolIds { uint128 src; uint128 dst; } function setConfig(uint16 version, uint16 eid, uint256 configType, bytes calldata config) external; function setSendVersion(uint16 version) external; function setReceiveVersion(uint16 version) external; function setTrustedRemote( uint256 remoteChainId, uint16 remoteEid, uint256 minGasAmount, bytes calldata path, PoolIds calldata poolIds ) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; import "./ILayerZeroUserApplicationConfig.sol"; interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig { // @notice send a LayerZero message to the specified address at a LayerZero endpoint. // @param _dstChainId - the destination chain identifier // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains // @param _payload - a custom bytes payload to send to the destination contract // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable; // @notice used by the messaging library to publish verified payload // @param _srcChainId - the source chain identifier // @param _srcAddress - the source contract (as bytes) at the source chain // @param _dstAddress - the address on destination chain // @param _nonce - the unbound message ordering nonce // @param _gasLimit - the gas limit for external contract execution // @param _payload - verified payload to send to the destination contract function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external; // @notice get the inboundNonce of a receiver from a source chain which could be EVM or non-EVM chain // @param _srcChainId - the source chain identifier // @param _srcAddress - the source chain contract address function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64); // @notice get the outboundNonce from this source chain which, consequently, is always an EVM // @param _srcAddress - the source chain contract address function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64); // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery // @param _dstChainId - the destination chain identifier // @param _userApplication - the user app address on this EVM chain // @param _payload - the custom message to send over LayerZero // @param _payInZRO - if false, user app pays the protocol fee in native token // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee); // @notice get this Endpoint's immutable source identifier function getChainId() external view returns (uint16); // @notice the interface to retry failed message on this Endpoint destination // @param _srcChainId - the source chain identifier // @param _srcAddress - the source chain contract address // @param _payload - the payload to be retried function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external; // @notice query if any STORED payload (message blocking) at the endpoint. // @param _srcChainId - the source chain identifier // @param _srcAddress - the source chain contract address function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool); // @notice query if the _libraryAddress is valid for sending msgs. // @param _userApplication - the user app address on this EVM chain function getSendLibraryAddress(address _userApplication) external view returns (address); // @notice query if the _libraryAddress is valid for receiving msgs. // @param _userApplication - the user app address on this EVM chain function getReceiveLibraryAddress(address _userApplication) external view returns (address); // @notice query if the non-reentrancy guard for send() is on // @return true if the guard is on. false otherwise function isSendingPayload() external view returns (bool); // @notice query if the non-reentrancy guard for receive() is on // @return true if the guard is on. false otherwise function isReceivingPayload() external view returns (bool); // @notice get the configuration of the LayerZero messaging library of the specified version // @param _version - messaging library version // @param _chainId - the chainId for the pending config change // @param _userApplication - the contract address of the user application // @param _configType - type of configuration. every messaging library has its own convention. function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory); // @notice get the send() LayerZero messaging library version // @param _userApplication - the contract address of the user application function getSendVersion(address _userApplication) external view returns (uint16); // @notice get the lzReceive() LayerZero messaging library version // @param _userApplication - the contract address of the user application function getReceiveVersion(address _userApplication) external view returns (uint16); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Simple single owner authorization mixin. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol) abstract contract Owned { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event OwnershipTransferred(address indexed user, address indexed newOwner); /*////////////////////////////////////////////////////////////// OWNERSHIP STORAGE //////////////////////////////////////////////////////////////*/ address public owner; modifier onlyOwner() virtual { require(msg.sender == owner, "UNAUTHORIZED"); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(address _owner) { owner = _owner; emit OwnershipTransferred(address(0), _owner); } /*////////////////////////////////////////////////////////////// OWNERSHIP LOGIC //////////////////////////////////////////////////////////////*/ function transferOwnership(address newOwner) public virtual onlyOwner { owner = newOwner; emit OwnershipTransferred(msg.sender, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; interface ILayerZeroReceiver { // @notice LayerZero endpoint will invoke this function to deliver the message on the destination // @param _srcChainId - the source endpoint identifier // @param _srcAddress - the source sending contract address from the source chain // @param _nonce - the ordered message nonce // @param _payload - the signed payload is the UA bytes has encoded to be sent function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.5.0; interface ILayerZeroUserApplicationConfig { // @notice set the configuration of the LayerZero messaging library of the specified version // @param _version - messaging library version // @param _chainId - the chainId for the pending config change // @param _configType - type of configuration. every messaging library has its own convention. // @param _config - configuration in the bytes. can encode arbitrary content. function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external; // @notice set the send() LayerZero messaging library version to _version // @param _version - new messaging library version function setSendVersion(uint16 _version) external; // @notice set the lzReceive() LayerZero messaging library version to _version // @param _version - new messaging library version function setReceiveVersion(uint16 _version) external; // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload // @param _srcChainId - the chainId of the source chain // @param _srcAddress - the contract address of the source contract at the source chain function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external; }
{ "remappings": [ "@openzeppelin/contracts/=lib/phuture-v2-contracts/lib/@openzeppelin/contracts/", "chainlink/=lib/phuture-v2-contracts/lib/chainlink-brownie-contracts/contracts/", "forge-std/=lib/forge-std/src/", "layerzero/=lib/phuture-v2-contracts/lib/LayerZero/contracts/", "redstone/=lib/phuture-v2-contracts/lib/redstone-oracles-monorepo/packages/evm-connector/contracts/", "solmate/=lib/phuture-v2-contracts/lib/solmate/src/", "src/=lib/phuture-v2-contracts/src/", "sstore2/=lib/phuture-v2-contracts/lib/sstore2/contracts/", "@chainlink/=node_modules/@chainlink/", "@eth-optimism/=node_modules/@eth-optimism/", "@openzeppelin/contracts-upgradeable/=lib/phuture-v2-contracts/lib/openzeppelin-contracts-upgradeable/contracts/", "@redstone-finance/=node_modules/@redstone-finance/", "LayerZero/=lib/phuture-v2-contracts/lib/LayerZero/contracts/", "chainlink-brownie-contracts/=lib/phuture-v2-contracts/lib/chainlink-brownie-contracts/contracts/src/v0.6/vendor/@arbitrum/nitro-contracts/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/phuture-v2-contracts/lib/@openzeppelin/lib/erc4626-tests/", "openzeppelin-contracts-upgradeable/=lib/phuture-v2-contracts/lib/openzeppelin-contracts-upgradeable/", "openzeppelin/=lib/phuture-v2-contracts/lib/@openzeppelin/contracts/", "phuture-v2-contracts/=lib/phuture-v2-contracts/", "redstone-oracles-monorepo/=lib/phuture-v2-contracts/lib/", "solady/=lib/phuture-v2-contracts/lib/solady/src/" ], "optimizer": { "enabled": true, "runs": 200, "details": { "constantOptimizer": true, "yul": true, "yulDetails": { "stackAllocation": true } } }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": false }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"_stargateComposer","type":"address"},{"internalType":"address payable","name":"_endpoint","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"uint16","name":"_homeEid","type":"uint16"},{"internalType":"address","name":"_sgETH","type":"address"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"}],"internalType":"struct OmnichainMessenger.NativeInfo","name":"_nativeInfo","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"}],"name":"BridgingCurrencyNotFound","type":"error"},{"inputs":[],"name":"ERC20TransferFailed","type":"error"},{"inputs":[],"name":"Forbidden","type":"error"},{"inputs":[],"name":"InsufficientValue","type":"error"},{"inputs":[],"name":"Invalid","type":"error"},{"inputs":[{"internalType":"uint256","name":"_size","type":"uint256"},{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_end","type":"uint256"}],"name":"InvalidCodeAtRange","type":"error"},{"inputs":[],"name":"NativeTransferFailed","type":"error"},{"inputs":[],"name":"OnlyEndpoint","type":"error"},{"inputs":[],"name":"OrderHashMismatch","type":"error"},{"inputs":[{"internalType":"uint16","name":"eid","type":"uint16"}],"name":"PathNotFound","type":"error"},{"inputs":[],"name":"PushOrders","type":"error"},{"inputs":[],"name":"QueryFailed","type":"error"},{"inputs":[],"name":"Set","type":"error"},{"inputs":[],"name":"WriteError","type":"error"},{"inputs":[],"name":"ZRONotSupported","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"OrdersHashClear","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"Currency","name":"buyCurrency","type":"address"}],"indexed":false,"internalType":"struct IOrderBook.BoughtOrder[]","name":"orders","type":"tuple[]"},{"indexed":false,"internalType":"uint256","name":"totalBought","type":"uint256"}],"name":"OutgoingOrders","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"remoteEid","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"path","type":"bytes"},{"components":[{"internalType":"uint128","name":"src","type":"uint128"},{"internalType":"uint128","name":"dst","type":"uint128"}],"indexed":false,"internalType":"struct IBlockingApp.PoolIds","name":"poolIds","type":"tuple"}],"name":"TrustedRemoteSet","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"eIds","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"Currency","name":"sellCurrency","type":"address"},{"internalType":"Currency","name":"localBuyCurrency","type":"address"},{"internalType":"Currency","name":"finalDestinationBuyCurrency","type":"address"},{"internalType":"uint256","name":"finalDestinationChainId","type":"uint256"}],"internalType":"struct OrderLib.OrderId[]","name":"orderIds","type":"tuple[]"},{"internalType":"uint256[]","name":"idIndices","type":"uint256[]"},{"internalType":"uint256[]","name":"pendingOrderCounts","type":"uint256[]"}],"internalType":"struct IOrderBook.FinishOrderExecutionParams","name":"orderBookParams","type":"tuple"},{"components":[{"internalType":"a160u96[]","name":"anatomyCurrencies","type":"uint256[]"},{"components":[{"internalType":"a160u96[]","name":"currencies","type":"uint256[]"},{"internalType":"uint256[]","name":"currencyIndexSet","type":"uint256[]"}],"internalType":"struct IVault.SnapshotAnatomy","name":"newAnatomy","type":"tuple"},{"components":[{"internalType":"uint256[]","name":"currencyIndexSet","type":"uint256[]"},{"internalType":"uint96[]","name":"amounts","type":"uint96[]"}],"internalType":"struct IVault.CurrencyWithdrawal","name":"withdrawals","type":"tuple"},{"internalType":"uint256","name":"lastKBalance","type":"uint256"},{"internalType":"Currency[]","name":"currencies","type":"address[]"}],"internalType":"struct IVault.EndRebalancingParams","name":"params","type":"tuple"},{"components":[{"components":[{"internalType":"uint256","name":"dstGasForCall","type":"uint256"},{"internalType":"uint256","name":"dstNativeAmount","type":"uint256"},{"internalType":"bytes","name":"dstNativeAddr","type":"bytes"}],"internalType":"struct IStargateRouter.lzTxObj","name":"lzTxObj","type":"tuple"},{"internalType":"uint256","name":"minAmountLD","type":"uint256"}],"internalType":"struct IOmnichainMessenger.SgParams[]","name":"sgParams","type":"tuple[]"},{"components":[{"internalType":"bytes[]","name":"options","type":"bytes[]"},{"internalType":"address","name":"zroPaymentAddress","type":"address"}],"internalType":"struct IOmnichainMessenger.LzParams","name":"lzParams","type":"tuple"},{"internalType":"address payable","name":"refundAddress","type":"address"}],"name":"finishVaultRebalancing","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcEid","type":"uint16"},{"internalType":"bytes","name":"srcAddress","type":"bytes"}],"name":"forceResumeReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBridgingInfo","outputs":[{"components":[{"internalType":"uint256","name":"finalDstChainId","type":"uint256"},{"internalType":"Currency","name":"localCurrency","type":"address"}],"internalType":"struct IOmnichainMessenger.BridgingInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"version","type":"uint16"},{"internalType":"uint16","name":"eid","type":"uint16"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"configType","type":"uint256"}],"name":"getConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lzEndpoint","outputs":[{"internalType":"contract ILayerZeroEndpoint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcEid","type":"uint16"},{"internalType":"bytes","name":"srcAddress","type":"bytes"},{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"minGasAmountForChain","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"phutureOnConsumeCallbackV1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIds","outputs":[{"internalType":"uint128","name":"src","type":"uint128"},{"internalType":"uint128","name":"dst","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"srcChainId","type":"uint256"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"Currency","name":"buyCurrency","type":"address"}],"internalType":"struct IOrderBook.BoughtOrder[]","name":"boughtOrders","type":"tuple[]"},{"internalType":"uint256","name":"boughtOrdersTotalAmount","type":"uint256"},{"internalType":"Currency","name":"currency","type":"address"},{"internalType":"uint256","name":"receivedAmount","type":"uint256"}],"name":"pushIncomingOrders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint96","name":"sellAmount","type":"uint96"},{"components":[{"internalType":"Currency","name":"sellCurrency","type":"address"},{"internalType":"Currency","name":"localBuyCurrency","type":"address"},{"internalType":"Currency","name":"finalDestinationBuyCurrency","type":"address"},{"internalType":"uint256","name":"finalDestinationChainId","type":"uint256"}],"internalType":"struct OrderLib.OrderId","name":"idParams","type":"tuple"}],"internalType":"struct OrderLib.Order[]","name":"orders","type":"tuple[]"},{"internalType":"uint128","name":"incomingOrders","type":"uint128"}],"internalType":"struct RebalancingLib.ChainOrders","name":"chainOrders","type":"tuple"}],"name":"pushOrders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"Currency[]","name":"currencies","type":"address[]"},{"internalType":"bytes32","name":"currenciesHash","type":"bytes32"}],"internalType":"struct IVault.RegisterCurrenciesResult","name":"info","type":"tuple"},{"internalType":"address payable","name":"refundAddress","type":"address"},{"components":[{"internalType":"bytes[]","name":"options","type":"bytes[]"},{"internalType":"address","name":"zroPaymentAddress","type":"address"}],"internalType":"struct IOmnichainMessenger.LzParams","name":"lzParams","type":"tuple"}],"name":"sendCurrenciesHash","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"finalDstChainId","type":"uint256"},{"internalType":"Currency","name":"localCurrency","type":"address"}],"internalType":"struct IOmnichainMessenger.BridgingInfo[]","name":"_infos","type":"tuple[]"}],"name":"setBridgingInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"version","type":"uint16"},{"internalType":"uint16","name":"eid","type":"uint16"},{"internalType":"uint256","name":"configType","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_escrowDeployer","type":"address"}],"name":"setEscrowDeployer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_orderBook","type":"address"}],"name":"setOrderBook","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"version","type":"uint16"}],"name":"setReceiveVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"version","type":"uint16"}],"name":"setSendVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"remoteChainId","type":"uint256"},{"internalType":"uint16","name":"remoteEid","type":"uint16"},{"internalType":"uint256","name":"minGasAmount","type":"uint256"},{"internalType":"bytes","name":"path","type":"bytes"},{"components":[{"internalType":"uint128","name":"src","type":"uint128"},{"internalType":"uint128","name":"dst","type":"uint128"}],"internalType":"struct IBlockingApp.PoolIds","name":"_poolIds","type":"tuple"}],"name":"setTrustedRemote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcEid","type":"uint16"},{"internalType":"bytes","name":"srcAddress","type":"bytes"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"sgReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"trustedRemotes","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"Currency","name":"currency","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawCurrency","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6040610120815234620004e0576200499090813803806200002081620004fb565b93843982019060e083830312620004e0576200003c8362000521565b6020906200004c82860162000521565b838601516001600160a01b03808216979094909291889003620004e057620000776060840162000521565b96608084015161ffff81168103620004e0576200009760a0860162000521565b60c08601516001600160401b0396919291878211620004e0570194606086850312620004e0578951936060850185811089821117620004e5578b528651888111620004e05781620000ea91890162000536565b855285870151888111620004e0578b916200010791890162000536565b9686860197885201519760ff89168903620004e057848b01988952600080546001600160a01b031916918b1691821781559c908d7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a360805260a05260e05260c0525197885192848411620003de576006549360019a8b86811c96168015620004d5575b85871014620004c1578190601f968781116200046d575b508590878311600114620003fe578592620003f2575b5050600019600383901b1c1916908b1b176006555b51918251948511620003de576007548a81811c91168015620003d3575b82821014620003bf5784811162000376575b5080938511600114620003085750978392839260ff9798999a94620002fc575b50501b916000199060031b1c1916176007555b511660ff19600854161760085561010092168252516143e79182620005a98339608051828181610446015281816105ec01528181610fb90152818161119e015281816113580152818161157b0152818161164801526138e3015260a0518281816124dd0152818161335b015281816135b4015281816136170152818161367d015281816136db015261371c015260c05182612572015260e051828181610eb201526117e201525181818161182601528181612ba501528181612df101528181612f2f0152612fa60152f35b0151925038806200021e565b9893929091601f198416996007845280842093905b8b82106200035e5750508360ff9798999a1062000344575b505050811b0160075562000231565b015160001960f88460031b161c1916905538808062000335565b8087859682949686015181550195019301906200031d565b600783528183208580880160051c820192848910620003b5575b0160051c01908b905b828110620003a9575050620001fe565b848155018b9062000399565b9250819262000390565b634e487b7160e01b83526022600452602483fd5b90607f1690620001ec565b634e487b7160e01b82526041600452602482fd5b015190503880620001ba565b600686528686208e94509190601f198416875b898282106200044d575050841162000433575b505050811b01600655620001cf565b015160001960f88460031b161c1916905538808062000424565b91929395968291958786015181550195019301908f959493929162000411565b909150600685528585208780850160051c820192888610620004b7575b918f91869594930160051c01915b828110620004a8575050620001a4565b8781558594508f910162000498565b925081926200048a565b634e487b7160e01b84526022600452602484fd5b95607f16956200018d565b600080fd5b634e487b7160e01b600052604160045260246000fd5b6040519190601f01601f191682016001600160401b03811183821017620004e557604052565b51906001600160a01b0382168203620004e057565b919080601f84011215620004e05782516001600160401b038111620004e5576020906200056c601f8201601f19168301620004fb565b92818452828287010111620004e05760005b8181106200059457508260009394955001015290565b85810183015184820184015282016200057e56fe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c80621d3567146101aa578063055f192c146101a557806307e0db17146101a05780630e73c0d31461019b57806310ddb1371461019657806318b8dac9146101915780632583c29c1461018c57806327a0371f146101875780632b5d23d214610182578063314012d11461017d5780633a26f9421461017857806342d65a8d1461017357806369883b4e1461016e5780637a7c7348146101695780638da5cb5b146101645780639a1598c81461015f578063ab8236f31461015a578063b353aaa714610155578063bee01be814610150578063c4f7941d1461014b578063cbed8b9c14610146578063ccfc9ba514610141578063d699e0af1461013c578063f2fde38b146101375763f5ecbdbc0361000e57611519565b6114a6565b61145c565b6113c3565b6112f8565b6112c8565b6111cd565b611188565b61111a565b6110ca565b6110a1565b611066565b61102a565b610f65565b610e4a565b610d2a565b610cdd565b610a65565b610914565b610643565b6105b9565b61052f565b610413565b61029e565b610203565b6004359061ffff821682036101c057565b600080fd5b6024359061ffff821682036101c057565b9181601f840112156101c0578235916001600160401b0383116101c057602083818601950101116101c057565b346101c05760803660031901126101c05761021c6101af565b6001600160401b03906024358281116101c05761023d9036906004016101d6565b604492919235848116036101c0576064359384116101c0576102666100199436906004016101d6565b939092611639565b9181601f840112156101c0578235916001600160401b0383116101c0576020808501948460061b0101116101c057565b346101c05760203660031901126101c0576004356001600160401b0381116101c0576102ce90369060040161026e565b60018060a01b03906000926102e78385541633146116e4565b604091825180926020820192808684016020865252606083019190885b878282106103f257505050506103a09261032c6103b093602e9303601f1981018752866109e3565b61035c60218751809361034c60208301998d8b5251809285850190610c81565b81010360018101845201826109e3565b80519486519485926020840197606360f81b895263ffffffff60e01b9060e01b1660218501526880600e6000396000f360b81b602585015251809285850190610c81565b810103600e8101845201826109e3565b519084f0918216156103e25750600980546001600160a01b0319166001600160a01b0390921691909117905580f35b80f35b5163046a55db60e11b8152600490fd5b839550846104056001949683949661171f565b019401910191859392610304565b346101c057600060203660031901126104af5761042e6101af565b8160018060a01b036104448183541633146116e4565b7f00000000000000000000000000000000000000000000000000000000000000001691823b156104ab57602461ffff918360405195869485936307e0db1760e01b85521660048401525af180156104a65761049d575080f35b6103df9061095f565b611740565b5080fd5b80fd5b908160a09103126101c05790565b9181601f840112156101c0578235916001600160401b0383116101c0576020808501948460051b0101116101c057565b60409060831901126101c057608490565b908160409103126101c05790565b6001600160a01b038116036101c057565b6084359061052d8261050f565b565b60031960a0368201126101c0576004356001600160401b03918282116101c05760609082360301126101c0576024358281116101c0576105739036906004016104b2565b6044358381116101c05761058b9036906004016104c0565b906064359485116101c0576105a7610019953690600401610501565b926105b0610520565b9460040161174c565b346101c057600060203660031901126104af576105d46101af565b8160018060a01b036105ea8183541633146116e4565b7f00000000000000000000000000000000000000000000000000000000000000001691823b156104ab57602461ffff918360405195869485936310ddb13760e01b85521660048401525af180156104a65761049d575080f35b346101c05760a03660031901126101c0576004356024356001600160401b0381116101c05761067690369060040161026e565b9091906064356044356106888261050f565b60843591604091825194602095868101816106a585858d85611f1c565b03916106b9601f19938481018352826109e3565b51902085518881019182526001600160a01b03861660208301526040820188905290916106f29082606085015b039081018352826109e3565b51902061070988600052600c602052604060002090565b5403610903577fc945d9e1f8095c0dea44c1e121710035a0e1825064e18e6e9d304e2cbf233c2061075b6000988961074b82600052600c602052604060002090565b5586519081529081906020820190565b0390a161076781611f7a565b9561077182611e6a565b988893845b8b8611156107f6578a8a818b8b8b6107a4610798600a5460018060a01b031690565b6001600160a01b031690565b91823b156107f2576107cd958591519687958694859363ad175a8b60e01b8552600485016120a6565b03925af180156104a6576107df575080f35b806107ec6103df9261095f565b80611096565b8480fd5b806001600160601b03866108d48f8f8f908f8f8f92908f958d8f93848f6108dd9f8b906108a5998f938361085c956108949a610868995082146000146108e35750505061084b9161084691611e79565b61399f565b9d5b6108628461085c84848a61200a565b01611e15565b9561200a565b93610883610874610a04565b6001600160a01b039098168852565b6001600160a01b0390911690860152565b6001600160a01b0390911690830152565b4660608201526108b3610a11565b6001600160601b0386168152908b8201526108ce838361201a565b5261201a565b50160195611ffb565b94610776565b6108fd945061084693916108f7918b61200a565b35613989565b9d61084d565b835163be364e3b60e01b8152600490fd5b346101c05760203660031901126101c05761ffff6109306101af565b1660005260056020526020604060002054604051908152f35b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161097257604052565b610949565b604081019081106001600160401b0382111761097257604052565b608081019081106001600160401b0382111761097257604052565b606081019081106001600160401b0382111761097257604052565b602081019081106001600160401b0382111761097257604052565b90601f801991011681019081106001600160401b0382111761097257604052565b6040519061052d82610992565b6040519061052d82610977565b6001600160401b0381116109725760051b60200190565b35906001600160601b03821682036101c057565b6001600160801b038116036101c057565b359061052d82610a49565b346101c057602060031981813601126101c057600435916001600160401b03918284116101c0576040809185360301126101c057805192610aa584610977565b84600401359081116101c0578401366023820112156101c057600481013590610acd82610a1e565b92610ada815194856109e3565b82845284840190602460a0809502840101923684116101c057602401915b838310610b1c576100198888610b1360248d8b855201610a5a565b90820152612120565b8236038581126101c057825191610b3283610977565b610b3b85610a35565b835260808092601f1901126101c05786928992855190610b5a82610992565b84880135610b678161050f565b825286880135610b768161050f565b8583015260609081890135610b8a8161050f565b888401528801359082015283820152815201920191610af8565b90600182811c92168015610bd4575b6020831014610bbe57565b634e487b7160e01b600052602260045260246000fd5b91607f1691610bb3565b90604051918260008254610bf181610ba4565b90818452602094600191600181169081600014610c5f5750600114610c20575b50505061052d925003836109e3565b600090815285812095935091905b818310610c4757505061052d9350820101388080610c11565b85548884018501529485019487945091830191610c2e565b9250505061052d94925060ff191682840152151560051b820101388080610c11565b60005b838110610c945750506000910152565b8181015183820152602001610c84565b90602091610cbd81518092818552858086019101610c81565b601f01601f1916010190565b906020610cda928181520190610ca4565b90565b346101c05760203660031901126101c05761ffff610cf96101af565b166000526003602052610d26610d126040600020610bde565b604051918291602083526020830190610ca4565b0390f35b346101c05760c03660031901126101c057610d436101c5565b6064356001600160401b0381116101c057610d837fa6c31f11fb022ad87f4d24c4d7341d7ff9914f0263c04421f24b33dc014efccd9136906004016101d6565b92610e44610d90366104f0565b600095610da760018060a01b0388541633146116e4565b600435875260026020526040872061ffff851661ffff198254161790556004602052604087208235610dd881610a49565b6001600160801b036020850135610dee81610a49565b81199060801b169116179055610e1c8186610e178761ffff166000526003602052604060002090565b61228c565b604435610e378561ffff166000526005602052604060002090565b556040519485948561237b565b0390a180f35b60603660031901126101c0576001600160401b036004358181116101c057610e76903690600401610501565b60243591610e838361050f565b6044359081116101c057610e9b903690600401610501565b610eb060018060a01b036000541633146116e4565b7f0000000000000000000000000000000000000000000000000000000000000000904793348503948511610f6057610f09610f4694610f17610efa610ef48761388c565b92613d18565b604051938491602083016123ce565b03601f1981018452836109e3565b610f40610f39610f33610f2c60208801611e15565b9680611e1f565b90611e9c565b3691611602565b946138ca565b4710610f4e57005b60405163044044a560e21b8152600490fd5b611e54565b346101c057600060403660031901126104af57610f806101af565b816024356001600160401b0381116104ab57610fa09036906004016101d6565b909260018060a01b03610fb78185541633146116e4565b7f00000000000000000000000000000000000000000000000000000000000000001690813b15611026578361ffff91611014604051978896879586946342d65a8d60e01b865216600485015260406024850152604484019161235a565b03925af180156104a65761049d575080f35b8380fd5b346101c05760203660031901126101c0576004356000526004602052604080600020548151906001600160801b038116825260801c6020820152f35b346101c05760203660031901126101c0576004356001600160401b0381116101c0576100199036906004016101d6565b60009103126101c057565b346101c05760003660031901126101c0576000546040516001600160a01b039091168152602090f35b346101c05760203660031901126101c0576004356110e78161050f565b6000546001600160a01b03919061110190831633146116e4565b166001600160601b0360a01b600a541617600a55600080f35b346101c05760c03660031901126101c0576111336101af565b6001600160401b03906024358281116101c0576111549036906004016101d6565b916064356111618161050f565b60a4359485116101c05761117c6100199536906004016101d6565b949093608435936124c8565b346101c05760003660031901126101c0576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346101c05760203660031901126101c0576004356111ea8161050f565b6000546001600160a01b03919061120490831633146116e4565b600b54829061121b906001600160a01b0316610798565b166112b657604051633cb747bf60e01b815290821691602082600481865afa9182156104a657600092611285575b503091160361127357600b80546001600160a01b0319166001600160a01b03909216919091179055005b604051636dac6a0960e01b8152600490fd5b6112a891925060203d6020116112af575b6112a081836109e3565b810190612645565b9038611249565b503d611296565b604051632081e91160e01b8152600490fd5b346101c05760203660031901126101c0576004356000526002602052602061ffff60406000205416604051908152f35b346101c05760803660031901126101c0576113116101af565b6113196101c5565b6064356001600160401b0381116101c0576113389036906004016101d6565b60018060a09493941b039160009483611356879586541633146116e4565b7f00000000000000000000000000000000000000000000000000000000000000001691823b156107f25784906107cd604051978896879586946332fb62e760e21b865261ffff8092166004870152166024850152604435604485015260806064850152608484019161235a565b346101c05760003660031901126101c0576009546113e9906001600160a01b03166141fe565b6113fe8151916020808094830101910161265a565b9060409160405192828493840190808552835180925280604086019401926000905b83821061142d5786860387f35b8451805187526020908101516001600160a01b0316908701528796509485019493820193600190910190611420565b346101c05760603660031901126101c05761001960043561147c8161050f565b6024356114888161050f565b61149d60018060a01b036000541633146116e4565b60443591613e96565b346101c05760203660031901126101c0576004356114c38161050f565b6000805490916001600160a01b03906114df33838516146116e4565b1680916001600160601b0360a01b16178255337f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b346101c05760803660031901126101c0576115326101af565b61153a6101c5565b9061154660443561050f565b604051633d7b2f6f60e21b815261ffff91821660048201529116602482015230604482015260648035908201526000816084817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156104a657610d26916000916115c4575b5060405191829182610cc9565b6115e191503d806000833e6115d981836109e3565b8101906126e6565b386115b7565b6001600160401b03811161097257601f01601f191660200190565b92919261160e826115e7565b9161161c60405193846109e3565b8294818452818301116101c0578281602093846000960137010152565b919093929360018060a01b03807f00000000000000000000000000000000000000000000000000000000000000001633149081156116d6575b50156116c45761168a6116a6916116ab933691611602565b602081519101209261ffff166000526003602052604060002090565b610bde565b60208151910120036116c05761052d91612ac8565b5050565b604051630fd72cd960e31b8152600490fd5b905060015416331438611672565b156116eb57565b60405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606490fd5b602080918035845201356117328161050f565b6001600160a01b0316910152565b6040513d6000823e3d90fd5b94919392909360018060a01b039560009261176b8885541633146116e4565b61177f46600052600c602052604060002090565b5461194457600a54849283916117bf91906117a2906001600160a01b0316610798565b9060405195868094819363474aba6b60e01b835260048301611bab565b03925af19283156104a6576117dd9387938691611922575b50613338565b6118227f000000000000000000000000000000000000000000000000000000000000000094604051809763099e120360e11b8252818581602096879660048301611d51565b03927f0000000000000000000000000000000000000000000000000000000000000000165af19081156104a65761052d966118ab93926118e7575b50610f396118c0610f40926118b96118748a61388c565b9561187d610a11565b9046825283820152604051978891848301919091604060206060830194600684528051828501520151910152565b03601f1981018852876109e3565b8701611e15565b956118da6118e16118d18380611e1f565b92909380611e1f565b9050611e6a565b91611edb565b8192506118c0611912610f3992610f40943d871161191b575b61190a81836109e3565b810190611c40565b9392505061185d565b503d611900565b61193e91503d8088833e61193681836109e3565b810190611987565b386117d7565b6040516370f1766760e01b8152600490fd5b91908260409103126101c05760405161196e81610977565b6020808294805184520151916119838361050f565b0152565b90602080838303126101c05782516001600160401b03938482116101c0570182601f820112156101c05780516119bc81610a1e565b946040946119cc865197886109e3565b828752848088019360051b850101938185116101c057858101935b8585106119f957505050505050505090565b84518481116101c0578201608080601f1983870301126101c057895191611a1f83610992565b8981015183528a810151611a328161050f565b8a840152606091828201518c850152810151908782116101c057019085603f830112156101c0578982015191611a6783610a1e565b92611a748d5194856109e3565b8084528c8c85019160061b830101918883116101c057908d808e97959896949301915b838310611ab2575050505083948201528152019401936119e7565b611ac48b849596989a97999394611956565b81520191018d8d969497959392611a97565b9190808252602080920192916000905b828210611af4575050505090565b909192936001908535611b068161050f565b828060a01b0380911682528084880135611b1f8161050f565b168483015260409081880135611b348161050f565b1690820152606086810135908201526080908101950193920190611ae6565b9035601e19823603018112156101c05701602081359101916001600160401b0382116101c0578160051b360383136101c057565b81835290916001600160fb1b0383116101c05760209260051b809284830137010190565b90602082528035601e19823603018112156101c057810191602083359301906001600160401b0384116101c0578360071b360382136101c057611bfe606092610cda958460208501526080840191611ad6565b90611c31611c26611c126020870187611b53565b601f19858703810160408701529591611b87565b946040810190611b53565b93909282860301910152611b87565b908160209103126101c0575190565b91908082526020809201929160005b828110611c6c575050505090565b833585529381019392810192600101611c5e565b9035603e19823603018112156101c0570190565b611caf611ca18280611b53565b604085526040850191611b87565b6020611cbf819382810190611b53565b9290948281830391015282815201929160005b828110611ce0575050505090565b9091929382806001926001600160601b03611cfa89610a35565b16815201950193929101611cd2565b91908082526020809201929160005b828110611d26575050505090565b9091929382806001928735611d3a8161050f565b848060a01b03168152019501910192919092611d18565b9060a0610cda9260208152611d79611d698480611b53565b84602085015260c0840191611c4f565b90611e06611df1611dd5611d906020880188611c80565b601f199586868203016040870152611dc7611dbc611dae8480611b53565b604085526040850191611c4f565b926020810190611b53565b916020818503910152611b87565b611de26040880188611c80565b85858303016060860152611c94565b94606081013560808401526080810190611b53565b93909282860301910152611d09565b35610cda8161050f565b903590601e19813603018212156101c057018035906001600160401b0382116101c057602001918160051b360383136101c057565b634e487b7160e01b600052601160045260246000fd5b600019810191908211610f6057565b91908203918211610f6057565b634e487b7160e01b600052603260045260246000fd5b9015611ed657803590601e19813603018212156101c05701908135916001600160401b0383116101c05760200182360381136101c0579190565b611e86565b9190811015611ed65760051b81013590601e19813603018212156101c05701908135916001600160401b0383116101c05760200182360381136101c0579190565b604080825280820184905290949392606086019160005b828110611f465750505060209150930152565b909192828082611f586001948961171f565b01950191019392919093611f33565b604051611f73816109c8565b6000815290565b90611f8482610a1e565b604090611f9460405191826109e3565b8381528093611fa5601f1991610a1e565b019160005b838110611fb75750505050565b6020908251611fc581610977565b60008152828451611fd581610992565b600081526000828201526000868201526000606082015281830152828601015201611faa565b6000198114610f605760010190565b9190811015611ed65760061b0190565b8051821015611ed65760209160051b010190565b90815180825260208080930193019160005b82811061204e575050505090565b835180516001600160601b0316865282015180516001600160a01b0390811687850152818401518116604080890191909152820151166060808801919091520151608086015260a09094019392810192600101612040565b6120be6040929594939560608352606083019061202e565b6001600160a01b0390951660208201520152565b6020815260406001600160801b0360206120f685518483870152606086019061202e565b9401511691015290565b6040906001600160801b03610cda9493168152816020820152019061202e565b60405160208101906121448161213685856120d2565b03601f1981018352826109e3565b51902061215b46600052600c602052604060002090565b540361222457600061217746600052600c602052604060002090565b556040514681527fc945d9e1f8095c0dea44c1e121710035a0e1825064e18e6e9d304e2cbf233c2090602090a180516121af816139b7565b600a546121da906020906121cb906001600160a01b0316610798565b9301516001600160801b031690565b90823b156101c057612206926000928360405180968195829463ad102f9b60e01b845260048401612100565b03925af180156104a6576122175750565b806107ec61052d9261095f565b60405163be364e3b60e01b8152600490fd5b90601f811161224457505050565b6000916000526020600020906020601f850160051c83019410612282575b601f0160051c01915b82811061227757505050565b81815560010161226b565b9092508290612262565b9092916001600160401b038111610972576122b1816122ab8454610ba4565b84612236565b6000601f82116001146122f25781906122e39394956000926122e7575b50508160011b916000199060031b1c19161790565b9055565b0135905038806122ce565b601f1982169461230784600052602060002090565b91805b878110612342575083600195969710612328575b505050811b019055565b0135600019600384901b60f8161c1916905538808061231e565b9092602060018192868601358155019401910161230a565b908060209392818452848401376000828201840152601f01601f1916010190565b929160609261ffff61239e9397969716855260806020860152608085019161235a565b9360208135916123ad83610a49565b6001600160801b03809316604086015201356123c881610a49565b16910152565b6040916000825260209260408484015260a0830182516040850152848301519460608080870152865180935260c086018260c08560051b8901019801946000925b85841061242a57505050505050506040608091015191015290565b90919293949598858060019260bf198c82030187528c5190856124696124596080855190808652850190610ca4565b8585015184820387860152610ca4565b9260ff89820151168984015281878060a01b03910151169101529b019401940192959493919061240f565b826014949392823701906001600160601b03199060601b1681520190565b91908260409103126101c0576020823592013590565b9495939490926001600160a01b0392909190337f00000000000000000000000000000000000000000000000000000000000000008516148015612628575b15612616576116a661255591612529966040519788916020830193309185612494565b039661253d601f19988981018352826109e3565b5190209261ffff166000526003602052604060002090565b602081519101200361260e5761052d956125ec926125a5928116907f000000000000000000000000000000000000000000000000000000000000000016810361260857506000945b8101906124b2565b60408051602081019384526001600160a01b038716918101919091526060810187905290936125d89082608081016106e6565b51902091600052600c602052604060002090565b55600a54612602906001600160a01b0316610798565b90613e96565b9461259d565b505050505050565b604051631dd2188d60e31b8152600490fd5b5060015461263e906001600160a01b0316610798565b3314612506565b908160209103126101c05751610cda8161050f565b906020916020818303126101c0578051906001600160401b0382116101c0570181601f820112156101c05780519261269184610a1e565b936040936126a260405196876109e3565b81865260208087019260061b850101938185116101c057602001915b8483106126ce5750505050505090565b8386916126db8486611956565b8152019201916126be565b6020818303126101c0578051906001600160401b0382116101c0570181601f820112156101c0578051612718816115e7565b9261272660405194856109e3565b818452602082840101116101c057610cda9160208085019101610c81565b906020116101c05790602090565b359060208110612760575090565b6000199060200360031b1b1690565b60ff8116036101c057565b91908260409103126101c057602082356127938161276f565b92013590565b604051906127a682610977565b60606020838281520152565b9060209081835260608301908051916040848601528251809152836080860193019060005b81811061282b57505050820151926040601f198284030191015281808451928381520193019160005b82811061280e575050505090565b83516001600160601b031685529381019392810192600101612800565b8251855293850193918501916001016127d7565b604090610cda93928152816020820152019061202e565b9080601f830112156101c057602090823561287081610a1e565b9361287e60405195866109e3565b81855260208086019260051b8201019283116101c057602001905b8282106128a7575050505090565b8380916128b384610a35565b815201910190612899565b916060838303126101c05782356128d48161276f565b926020808201359360408301356001600160401b03938482116101c05701906040828203126101c0576040519361290a85610977565b82358181116101c057830182601f820112156101c05780359061292c82610a1e565b9161293a60405193846109e3565b808352868084019160051b830101918583116101c05787809101915b83831061297f57505050508552838301359081116101c0576129789201612856565b9082015290565b8235815291810191889101612956565b9080601f830112156101c057816020610cda93359101611602565b906080828203126101c05781356129c08161276f565b9260208301356129cf8161050f565b9260408101359260608201356001600160401b0381116101c057610cda920161298f565b519081151582036101c057565b91908260409103126101c057610cda60208351612a1c8161050f565b93016129f3565b610cda9392606092825260208201528160408201520190610ca4565b916060838303126101c0578235612a558161276f565b926020810135612a648161050f565b9260408201356001600160401b0381116101c057610cda920161298f565b906060610cda9260008152600060208201528160408201520190610ca4565b908160609103126101c0578035612ab78161276f565b91604060208301356127938161050f565b60ff612ae6612ae0612ada8585612744565b90612752565b60ff1690565b1660018103612c1f575080612b4e92612b00920190612aa1565b600b546001600160a01b039493509091604091859190612b21908316610798565b835163701c61ed60e11b8152919092166001600160a01b0316600482015293849190829081906024820190565b03915afa9283156104a657612ba193602093600091612bef575b50604051632df8a21160e11b81526001600160a01b03909116600482015260248101929092529092839190829060009082906044820190565b03927f0000000000000000000000000000000000000000000000000000000000000000165af180156104a657612bd45750565b612bec9060203d60201161191b5761190a81836109e3565b50565b612c11915060403d604011612c18575b612c0981836109e3565b810190612a00565b5038612b68565b503d612bff565b60028103612d535750612c3491810190612a3f565b600b546001600160a01b039283169350909190612c52908216610798565b6040805163701c61ed60e11b81526001600160a01b0386166004820152909490918583602481845afa80156104a657600093600091612d30575b5015612ccc575b50501691823b156101c0576000928392612cc1925194858094819363216f3c6b60e01b835260048301612a82565b03925af16122175750565b8551634c96a38960e01b81526001600160a01b03929092166004830152602090829060249082906000905af19081612d11575b50612d0a5750505050565b3880612c93565b612d299060203d6020116112af576112a081836109e3565b5038612cff565b9050612d4a919350863d8811612c1857612c0981836109e3565b92909238612c8c565b60038103612f015750612d68918101906129aa565b600b546001600160a01b039384169450909190612d86908416610798565b6040805163701c61ed60e11b81526001600160a01b038716600482015290959194918682602481895afa80156104a657600092600091612ede575b508751632df8a21160e11b81526001600160a01b03841660048201526024810186905296602091828960448160007f00000000000000000000000000000000000000000000000000000000000000008b165af19889156104a657600099612ebf575b5015612e59575b5050501690813b156101c05760008094612cc196519687958694859363216f3c6b60e01b855260048501612a23565b8851634c96a38960e01b81526001600160a01b039390931660048401528190839060249082906000905af19182612ea1575b5050612e9957505050505050565b388080612e2a565b81612eb792903d106112af576112a081836109e3565b503880612e8b565b612ed7919950833d851161191b5761190a81836109e3565b9738612e23565b9050612ef8919250873d8911612c1857612c0981836109e3565b91909138612dc1565b60048103612f845750612f16918101906128be565b9150612f2c46600052600c602052604060002090565b557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b156101c057604051630e8f3bf560e31b815291600091839182908490829061220690600483016127b2565b600581036130695750612f999181019061277a565b919050612fa4612799565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690813b156101c057612ffb6040518093818094630e8f3bf560e31b825260009687958692600483016127b2565b03925af180156104a657613056575b50600a54613020906001600160a01b0316610798565b613028611f67565b90803b156130525761220693948360405180968195829463ad102f9b60e01b84526004840161283f565b8280fd5b806107ec6130639261095f565b3861300a565b600714613074575050565b6130809181019061277a565b600a54909150613098906001600160a01b0316610798565b803b156101c057604051630ca3008d60e01b815260048101929092526000908290602490829084905af180156104a6576122175750565b604051906130dc82610992565b606080836000815260006020820152600060408201520152565b9060405161310381610977565b91546001600160801b038116835260801c6020830152565b9190811015611ed65760051b81013590603e19813603018212156101c0570190565b9291906040906040850160408652815180915260608601916020809101936000905b838210613173575050505060209150930152565b8551805186526020908101516001600160a01b031690860152948201949384019360019091019061315f565b90602082519201516001600160601b03199081811693601481106131c257505050565b60140360031b82901b16169150565b90604051916001600160601b03191660208301526014825261052d82610977565b903590605e19813603018212156101c0570190565b91908260409103126101c0576020825192015190565b80358252602081013560208301526040810135601e19823603018112156101c05701602081359101906001600160401b0381116101c05780360382136101c057606083816040610cda960152019161235a565b9261329b610cda959361ffff6132a9941686526001602087015260a0604087015260a0860190610ca4565b908482036060860152610ca4565b91608081840391015261321d565b91908201809211610f6057565b979461331b94613329979293610cda9b999561ffff61012096168c526001600160801b0380921660208d01521660408b015260018060a01b031660608a0152608089015260a08801528060c088015286019061321d565b9084820360e0860152610ca4565b91610100818403910152610ca4565b9193926133436130cf565b60405163c45a015560e01b81529093906020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa80156104a6576133a59160009161386d575b506001600160a01b03168552565b8051946040850195865260005b8651811015613863576133c5818461201a565b51906134606133ea6133e284516000526002602052604060002090565b5461ffff1690565b926133f48461388c565b60608a015261341661341182516000526004602052604060002090565b6130f6565b60408201518a51602090613432906001600160a01b0316610798565b835160405163068bcd8d60e01b81526001600160801b03909116600482015295869190829081906024820190565b03915afa9384156104a657600494602091600091613846575b5060405163feb56b1560e01b815295869182906001600160a01b03165afa9081156104a657898b928f928e97600092613825575b50106137ad57509161358461357f60606134de613537958998976134d8602061356c9c01518d611e79565b9161311b565b966135788288017f37a28c62bfa8e4579bdc54985bb8380deeb34721706ffd1aac79b28b6a00d683815160408b01519061351d6040519283928361313d565b0390a151604089015160405198899160208301938461313d565b039761354b601f19998a81018352826109e3565b5190206040805160208101929092524690820152998a979088906060820190565b039081018852876109e3565b015161319f565b6131d1565b93604085896135b061359685806131f2565b8451630a51236960e01b81529a8b94859460048601613270565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9586156104a65760009661377b575b506020840180519096939084906001600160a01b031615613763575b5086516040860151613645917f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b0316614036565b604061366c602061365d86516001600160801b031690565b9501516001600160801b031690565b9501519061367a83806131f2565b967f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163b156101c0576000976020956136d7946040519d8e9a8b998a996327efc43f60e21b8b52013593309260048b016132c4565b03917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af19081156104a65760019361374a92613750575b50517f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b0316613f2e565b016133b2565b806107ec61375d9261095f565b38613718565b6137749194506040860151906132b7565b9238613609565b61379e91965060403d6040116137a6575b61379681836109e3565b810190613207565b5094386135ed565b503d61378c565b925050506001946121366137e26060806138209701519501515160405192839160208301919060206040840193600781520152565b613818610f398d60206138006137f9828901611e15565b9780611e1f565b919092019182519261381184611ffb565b9052611edb565b9330926138ca565b61374a565b61383f91925060203d60201161191b5761190a81836109e3565b90386134ad565b61385d9150823d84116112af576112a081836109e3565b38613479565b5095505050505050565b613886915060203d6020116112af576112a081836109e3565b38613397565b61ffff16908160005260036020526138a76040600020610bde565b918251156138b25750565b60249060405190639cd86f1760e01b82526004820152fd5b929493909291906001600160a01b0390811661397757807f000000000000000000000000000000000000000000000000000000000000000016924791843b156101c0576139499760009761ffff956122069361395c6040519c8d9b8c9a8b9962c5803160e81b8b521660048a015260c060248a015260c4890190610ca4565b60031993848983030160448a0152610ca4565b931660648601528960848601528483030160a4850152610ca4565b60405163653626cf60e01b8152600490fd5b816000190481118202158302156101c057020490565b600160601b8110156101c0576001600160601b031690565b6009546139cc906001600160a01b03166141fe565b906139e28251926020808095830101910161265a565b60005b8251811015613ab2576060846139fb838661201a565b5101510151468103613a11575b506001016139e5565b92909493600094855b8451811015613aa757613a2d818661201a565b51518614613a3d57600101613a1a565b90969294919550613a85613a6687613a576001948861201a565b5101516001600160a01b031690565b8780613a72878a61201a565b5101516001600160a01b03909216910152565b613a085760405163132b474b60e31b81526004810191909152602490fd5b0390fd5b509591939094613a85565b50505050565b60405190613ac5826109ad565b6000604083828152606060208201520152565b90613ae282610a1e565b604090613af260405191826109e3565b8381528093613b03601f1991610a1e565b019160009160005b848110613b19575050505050565b6020908351613b2781610992565b606080825286849180838501528188850152830152828501015201613b0b565b9190811015611ed65760051b0190565b908160209103126101c05751610cda8161276f565b6040519060008260075491613b8083610ba4565b80835292602090600190818116908115613c0c5750600114613bab575b505061052d925003836109e3565b91509260076000527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688936000925b828410613bf4575061052d9450505081016020013880613b9d565b85548885018301529485019487945092810192613bd9565b9150506020925061052d94915060ff191682840152151560051b8201013880613b9d565b60405190613c3d826109ad565b6040516006548391600081613c5184610ba4565b9182825260209460019086600182169182600014613cf8575050600114613c9b575b50613c80925003826109e3565b8252613c8a613b6c565b90820152604060ff60085416910152565b85915060066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f906000915b858310613ce0575050613c80935082010138613c73565b80548388018501528694508793909201918101613cc9565b60ff191685820152613c8095151560051b8501019250389150613c739050565b90613d21613ab8565b91602092604093808301356040830152468252613d48613d418480611e1f565b9050613ad8565b9281830193845260009260005b613d5f8380611e1f565b9050811015613e8d57613d84613d7f82613d798680611e1f565b90613b47565b611e15565b9084896001600160a01b03841680613e015750613df991613dec600195613ddc8694613dae613c30565b90613dc28183519784015193015160ff1690565b91613dcb610a04565b9687528d87015285019060ff169052565b6001600160a01b03166060830152565b8951906108ce838361201a565b505b01613d55565b905060049150613e10816140cc565b87613e1a8361418a565b928d519485809263313ce56760e01b82525afa9182156104a657600195613ddc86948f613dec94613e58988f8f9094613e5e575b5050613dcb610a04565b50613dfb565b613e7e929450803d10613e86575b613e7681836109e3565b810190613b57565b91388e613e4e565b503d613e6c565b50955050505050565b8215613f29576001600160a01b03818116613ed557505060008080613ebd9481945af11590565b613ec357565b604051633d2cec6f60e21b8152600490fd5b60209260008093613f11966044946040519463a9059cbb60e01b865216600485015260248401525af1600051600114601f3d11163d1517161590565b613f1757565b604051633c9fd93960e21b8152600490fd5b505050565b6001600160a01b031680156116c05760405163095ea7b360e01b602082018181526001600160a01b0385166024840152600060448401819052919492939290918085606481015b0393613f89601f19958681018952886109e3565b86519082875af1613f9861407e565b81614007575b5080613ffd575b15613fb2575b5050505050565b60405160208101959095526001600160a01b0316602485015260006044850152613ff393613fee91613fe89082606481016106e6565b82614268565b614268565b3880808080613fab565b50823b1515613fa5565b805180159250821561401c575b505038613f9e565b61402f9250602080918301019101614254565b3880614014565b6001600160a01b03168015613f295760405163095ea7b360e01b602082018181526001600160a01b038516602484015260448301959095529390926000808560648101613f75565b3d156140a9573d9061408f826115e7565b9161409d60405193846109e3565b82523d6000602084013e565b606090565b8015610f60576000190190565b908151811015611ed6570160200190565b6000809160405160208101906306fdde0360e01b8252600481526140ef81610977565b51915afa906140fc61407e565b9115614178578151602081036141655750602082815b6141195752565b9061414d61414061413261412c84611e6a565b856140bb565b516001600160f81b03191690565b6001600160f81b03191690565b6141615761415a906140ae565b9081614112565b9052565b91602080610cda939483010191016126e6565b6040516360d806dd60e11b8152600490fd5b6000809160405160208101906395d89b4160e01b8252600481526141ad81610977565b51915afa906141ba61407e565b9115614178578151602081036141655750602082815b6141d75752565b906141ea61414061413261412c84611e6a565b614161576141f7906140ae565b90816141d0565b90813b8015614245578060011161424557600019016001198082101561423e57505b600160405193601f19603f840116850160405282855260208501903c565b9050614220565b509050604051611f73816109c8565b908160209103126101c057610cda906129f3565b6040516142c6916001600160a01b031661428182610977565b6000806020958685527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656487860152868151910182855af16142c061407e565b9161434e565b805190828215928315614336575b505050156142df5750565b6084906040519062461bcd60e51b82526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152fd5b6143469350820181019101614254565b3882816142d4565b919290156143b05750815115614362575090565b3b1561436b5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156143c35750805190602001fd5b60405162461bcd60e51b815260206004820152908190613aa3906024830190610ca456000000000000000000000000de4d377d8a8d455330edd7c4eb5b284ada1113d8000000000000000000000000ecc19e177d24551aa7ed6bc6fe566eca726cc8a90000000000000000000000003c2269811836af69497e5f486a85d7316753cf62000000000000000000000000e903f5a1d43d93407bcd11c771c03628539414d2000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000007506f6c79676f6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054d41544943000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c80621d3567146101aa578063055f192c146101a557806307e0db17146101a05780630e73c0d31461019b57806310ddb1371461019657806318b8dac9146101915780632583c29c1461018c57806327a0371f146101875780632b5d23d214610182578063314012d11461017d5780633a26f9421461017857806342d65a8d1461017357806369883b4e1461016e5780637a7c7348146101695780638da5cb5b146101645780639a1598c81461015f578063ab8236f31461015a578063b353aaa714610155578063bee01be814610150578063c4f7941d1461014b578063cbed8b9c14610146578063ccfc9ba514610141578063d699e0af1461013c578063f2fde38b146101375763f5ecbdbc0361000e57611519565b6114a6565b61145c565b6113c3565b6112f8565b6112c8565b6111cd565b611188565b61111a565b6110ca565b6110a1565b611066565b61102a565b610f65565b610e4a565b610d2a565b610cdd565b610a65565b610914565b610643565b6105b9565b61052f565b610413565b61029e565b610203565b6004359061ffff821682036101c057565b600080fd5b6024359061ffff821682036101c057565b9181601f840112156101c0578235916001600160401b0383116101c057602083818601950101116101c057565b346101c05760803660031901126101c05761021c6101af565b6001600160401b03906024358281116101c05761023d9036906004016101d6565b604492919235848116036101c0576064359384116101c0576102666100199436906004016101d6565b939092611639565b9181601f840112156101c0578235916001600160401b0383116101c0576020808501948460061b0101116101c057565b346101c05760203660031901126101c0576004356001600160401b0381116101c0576102ce90369060040161026e565b60018060a01b03906000926102e78385541633146116e4565b604091825180926020820192808684016020865252606083019190885b878282106103f257505050506103a09261032c6103b093602e9303601f1981018752866109e3565b61035c60218751809361034c60208301998d8b5251809285850190610c81565b81010360018101845201826109e3565b80519486519485926020840197606360f81b895263ffffffff60e01b9060e01b1660218501526880600e6000396000f360b81b602585015251809285850190610c81565b810103600e8101845201826109e3565b519084f0918216156103e25750600980546001600160a01b0319166001600160a01b0390921691909117905580f35b80f35b5163046a55db60e11b8152600490fd5b839550846104056001949683949661171f565b019401910191859392610304565b346101c057600060203660031901126104af5761042e6101af565b8160018060a01b036104448183541633146116e4565b7f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf621691823b156104ab57602461ffff918360405195869485936307e0db1760e01b85521660048401525af180156104a65761049d575080f35b6103df9061095f565b611740565b5080fd5b80fd5b908160a09103126101c05790565b9181601f840112156101c0578235916001600160401b0383116101c0576020808501948460051b0101116101c057565b60409060831901126101c057608490565b908160409103126101c05790565b6001600160a01b038116036101c057565b6084359061052d8261050f565b565b60031960a0368201126101c0576004356001600160401b03918282116101c05760609082360301126101c0576024358281116101c0576105739036906004016104b2565b6044358381116101c05761058b9036906004016104c0565b906064359485116101c0576105a7610019953690600401610501565b926105b0610520565b9460040161174c565b346101c057600060203660031901126104af576105d46101af565b8160018060a01b036105ea8183541633146116e4565b7f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf621691823b156104ab57602461ffff918360405195869485936310ddb13760e01b85521660048401525af180156104a65761049d575080f35b346101c05760a03660031901126101c0576004356024356001600160401b0381116101c05761067690369060040161026e565b9091906064356044356106888261050f565b60843591604091825194602095868101816106a585858d85611f1c565b03916106b9601f19938481018352826109e3565b51902085518881019182526001600160a01b03861660208301526040820188905290916106f29082606085015b039081018352826109e3565b51902061070988600052600c602052604060002090565b5403610903577fc945d9e1f8095c0dea44c1e121710035a0e1825064e18e6e9d304e2cbf233c2061075b6000988961074b82600052600c602052604060002090565b5586519081529081906020820190565b0390a161076781611f7a565b9561077182611e6a565b988893845b8b8611156107f6578a8a818b8b8b6107a4610798600a5460018060a01b031690565b6001600160a01b031690565b91823b156107f2576107cd958591519687958694859363ad175a8b60e01b8552600485016120a6565b03925af180156104a6576107df575080f35b806107ec6103df9261095f565b80611096565b8480fd5b806001600160601b03866108d48f8f8f908f8f8f92908f958d8f93848f6108dd9f8b906108a5998f938361085c956108949a610868995082146000146108e35750505061084b9161084691611e79565b61399f565b9d5b6108628461085c84848a61200a565b01611e15565b9561200a565b93610883610874610a04565b6001600160a01b039098168852565b6001600160a01b0390911690860152565b6001600160a01b0390911690830152565b4660608201526108b3610a11565b6001600160601b0386168152908b8201526108ce838361201a565b5261201a565b50160195611ffb565b94610776565b6108fd945061084693916108f7918b61200a565b35613989565b9d61084d565b835163be364e3b60e01b8152600490fd5b346101c05760203660031901126101c05761ffff6109306101af565b1660005260056020526020604060002054604051908152f35b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161097257604052565b610949565b604081019081106001600160401b0382111761097257604052565b608081019081106001600160401b0382111761097257604052565b606081019081106001600160401b0382111761097257604052565b602081019081106001600160401b0382111761097257604052565b90601f801991011681019081106001600160401b0382111761097257604052565b6040519061052d82610992565b6040519061052d82610977565b6001600160401b0381116109725760051b60200190565b35906001600160601b03821682036101c057565b6001600160801b038116036101c057565b359061052d82610a49565b346101c057602060031981813601126101c057600435916001600160401b03918284116101c0576040809185360301126101c057805192610aa584610977565b84600401359081116101c0578401366023820112156101c057600481013590610acd82610a1e565b92610ada815194856109e3565b82845284840190602460a0809502840101923684116101c057602401915b838310610b1c576100198888610b1360248d8b855201610a5a565b90820152612120565b8236038581126101c057825191610b3283610977565b610b3b85610a35565b835260808092601f1901126101c05786928992855190610b5a82610992565b84880135610b678161050f565b825286880135610b768161050f565b8583015260609081890135610b8a8161050f565b888401528801359082015283820152815201920191610af8565b90600182811c92168015610bd4575b6020831014610bbe57565b634e487b7160e01b600052602260045260246000fd5b91607f1691610bb3565b90604051918260008254610bf181610ba4565b90818452602094600191600181169081600014610c5f5750600114610c20575b50505061052d925003836109e3565b600090815285812095935091905b818310610c4757505061052d9350820101388080610c11565b85548884018501529485019487945091830191610c2e565b9250505061052d94925060ff191682840152151560051b820101388080610c11565b60005b838110610c945750506000910152565b8181015183820152602001610c84565b90602091610cbd81518092818552858086019101610c81565b601f01601f1916010190565b906020610cda928181520190610ca4565b90565b346101c05760203660031901126101c05761ffff610cf96101af565b166000526003602052610d26610d126040600020610bde565b604051918291602083526020830190610ca4565b0390f35b346101c05760c03660031901126101c057610d436101c5565b6064356001600160401b0381116101c057610d837fa6c31f11fb022ad87f4d24c4d7341d7ff9914f0263c04421f24b33dc014efccd9136906004016101d6565b92610e44610d90366104f0565b600095610da760018060a01b0388541633146116e4565b600435875260026020526040872061ffff851661ffff198254161790556004602052604087208235610dd881610a49565b6001600160801b036020850135610dee81610a49565b81199060801b169116179055610e1c8186610e178761ffff166000526003602052604060002090565b61228c565b604435610e378561ffff166000526005602052604060002090565b556040519485948561237b565b0390a180f35b60603660031901126101c0576001600160401b036004358181116101c057610e76903690600401610501565b60243591610e838361050f565b6044359081116101c057610e9b903690600401610501565b610eb060018060a01b036000541633146116e4565b7f000000000000000000000000000000000000000000000000000000000000006e904793348503948511610f6057610f09610f4694610f17610efa610ef48761388c565b92613d18565b604051938491602083016123ce565b03601f1981018452836109e3565b610f40610f39610f33610f2c60208801611e15565b9680611e1f565b90611e9c565b3691611602565b946138ca565b4710610f4e57005b60405163044044a560e21b8152600490fd5b611e54565b346101c057600060403660031901126104af57610f806101af565b816024356001600160401b0381116104ab57610fa09036906004016101d6565b909260018060a01b03610fb78185541633146116e4565b7f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf621690813b15611026578361ffff91611014604051978896879586946342d65a8d60e01b865216600485015260406024850152604484019161235a565b03925af180156104a65761049d575080f35b8380fd5b346101c05760203660031901126101c0576004356000526004602052604080600020548151906001600160801b038116825260801c6020820152f35b346101c05760203660031901126101c0576004356001600160401b0381116101c0576100199036906004016101d6565b60009103126101c057565b346101c05760003660031901126101c0576000546040516001600160a01b039091168152602090f35b346101c05760203660031901126101c0576004356110e78161050f565b6000546001600160a01b03919061110190831633146116e4565b166001600160601b0360a01b600a541617600a55600080f35b346101c05760c03660031901126101c0576111336101af565b6001600160401b03906024358281116101c0576111549036906004016101d6565b916064356111618161050f565b60a4359485116101c05761117c6100199536906004016101d6565b949093608435936124c8565b346101c05760003660031901126101c0576040517f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b03168152602090f35b346101c05760203660031901126101c0576004356111ea8161050f565b6000546001600160a01b03919061120490831633146116e4565b600b54829061121b906001600160a01b0316610798565b166112b657604051633cb747bf60e01b815290821691602082600481865afa9182156104a657600092611285575b503091160361127357600b80546001600160a01b0319166001600160a01b03909216919091179055005b604051636dac6a0960e01b8152600490fd5b6112a891925060203d6020116112af575b6112a081836109e3565b810190612645565b9038611249565b503d611296565b604051632081e91160e01b8152600490fd5b346101c05760203660031901126101c0576004356000526002602052602061ffff60406000205416604051908152f35b346101c05760803660031901126101c0576113116101af565b6113196101c5565b6064356001600160401b0381116101c0576113389036906004016101d6565b60018060a09493941b039160009483611356879586541633146116e4565b7f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf621691823b156107f25784906107cd604051978896879586946332fb62e760e21b865261ffff8092166004870152166024850152604435604485015260806064850152608484019161235a565b346101c05760003660031901126101c0576009546113e9906001600160a01b03166141fe565b6113fe8151916020808094830101910161265a565b9060409160405192828493840190808552835180925280604086019401926000905b83821061142d5786860387f35b8451805187526020908101516001600160a01b0316908701528796509485019493820193600190910190611420565b346101c05760603660031901126101c05761001960043561147c8161050f565b6024356114888161050f565b61149d60018060a01b036000541633146116e4565b60443591613e96565b346101c05760203660031901126101c0576004356114c38161050f565b6000805490916001600160a01b03906114df33838516146116e4565b1680916001600160601b0360a01b16178255337f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b346101c05760803660031901126101c0576115326101af565b61153a6101c5565b9061154660443561050f565b604051633d7b2f6f60e21b815261ffff91821660048201529116602482015230604482015260648035908201526000816084817f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b03165afa80156104a657610d26916000916115c4575b5060405191829182610cc9565b6115e191503d806000833e6115d981836109e3565b8101906126e6565b386115b7565b6001600160401b03811161097257601f01601f191660200190565b92919261160e826115e7565b9161161c60405193846109e3565b8294818452818301116101c0578281602093846000960137010152565b919093929360018060a01b03807f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf621633149081156116d6575b50156116c45761168a6116a6916116ab933691611602565b602081519101209261ffff166000526003602052604060002090565b610bde565b60208151910120036116c05761052d91612ac8565b5050565b604051630fd72cd960e31b8152600490fd5b905060015416331438611672565b156116eb57565b60405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606490fd5b602080918035845201356117328161050f565b6001600160a01b0316910152565b6040513d6000823e3d90fd5b94919392909360018060a01b039560009261176b8885541633146116e4565b61177f46600052600c602052604060002090565b5461194457600a54849283916117bf91906117a2906001600160a01b0316610798565b9060405195868094819363474aba6b60e01b835260048301611bab565b03925af19283156104a6576117dd9387938691611922575b50613338565b6118227f000000000000000000000000000000000000000000000000000000000000006e94604051809763099e120360e11b8252818581602096879660048301611d51565b03927f000000000000000000000000e903f5a1d43d93407bcd11c771c03628539414d2165af19081156104a65761052d966118ab93926118e7575b50610f396118c0610f40926118b96118748a61388c565b9561187d610a11565b9046825283820152604051978891848301919091604060206060830194600684528051828501520151910152565b03601f1981018852876109e3565b8701611e15565b956118da6118e16118d18380611e1f565b92909380611e1f565b9050611e6a565b91611edb565b8192506118c0611912610f3992610f40943d871161191b575b61190a81836109e3565b810190611c40565b9392505061185d565b503d611900565b61193e91503d8088833e61193681836109e3565b810190611987565b386117d7565b6040516370f1766760e01b8152600490fd5b91908260409103126101c05760405161196e81610977565b6020808294805184520151916119838361050f565b0152565b90602080838303126101c05782516001600160401b03938482116101c0570182601f820112156101c05780516119bc81610a1e565b946040946119cc865197886109e3565b828752848088019360051b850101938185116101c057858101935b8585106119f957505050505050505090565b84518481116101c0578201608080601f1983870301126101c057895191611a1f83610992565b8981015183528a810151611a328161050f565b8a840152606091828201518c850152810151908782116101c057019085603f830112156101c0578982015191611a6783610a1e565b92611a748d5194856109e3565b8084528c8c85019160061b830101918883116101c057908d808e97959896949301915b838310611ab2575050505083948201528152019401936119e7565b611ac48b849596989a97999394611956565b81520191018d8d969497959392611a97565b9190808252602080920192916000905b828210611af4575050505090565b909192936001908535611b068161050f565b828060a01b0380911682528084880135611b1f8161050f565b168483015260409081880135611b348161050f565b1690820152606086810135908201526080908101950193920190611ae6565b9035601e19823603018112156101c05701602081359101916001600160401b0382116101c0578160051b360383136101c057565b81835290916001600160fb1b0383116101c05760209260051b809284830137010190565b90602082528035601e19823603018112156101c057810191602083359301906001600160401b0384116101c0578360071b360382136101c057611bfe606092610cda958460208501526080840191611ad6565b90611c31611c26611c126020870187611b53565b601f19858703810160408701529591611b87565b946040810190611b53565b93909282860301910152611b87565b908160209103126101c0575190565b91908082526020809201929160005b828110611c6c575050505090565b833585529381019392810192600101611c5e565b9035603e19823603018112156101c0570190565b611caf611ca18280611b53565b604085526040850191611b87565b6020611cbf819382810190611b53565b9290948281830391015282815201929160005b828110611ce0575050505090565b9091929382806001926001600160601b03611cfa89610a35565b16815201950193929101611cd2565b91908082526020809201929160005b828110611d26575050505090565b9091929382806001928735611d3a8161050f565b848060a01b03168152019501910192919092611d18565b9060a0610cda9260208152611d79611d698480611b53565b84602085015260c0840191611c4f565b90611e06611df1611dd5611d906020880188611c80565b601f199586868203016040870152611dc7611dbc611dae8480611b53565b604085526040850191611c4f565b926020810190611b53565b916020818503910152611b87565b611de26040880188611c80565b85858303016060860152611c94565b94606081013560808401526080810190611b53565b93909282860301910152611d09565b35610cda8161050f565b903590601e19813603018212156101c057018035906001600160401b0382116101c057602001918160051b360383136101c057565b634e487b7160e01b600052601160045260246000fd5b600019810191908211610f6057565b91908203918211610f6057565b634e487b7160e01b600052603260045260246000fd5b9015611ed657803590601e19813603018212156101c05701908135916001600160401b0383116101c05760200182360381136101c0579190565b611e86565b9190811015611ed65760051b81013590601e19813603018212156101c05701908135916001600160401b0383116101c05760200182360381136101c0579190565b604080825280820184905290949392606086019160005b828110611f465750505060209150930152565b909192828082611f586001948961171f565b01950191019392919093611f33565b604051611f73816109c8565b6000815290565b90611f8482610a1e565b604090611f9460405191826109e3565b8381528093611fa5601f1991610a1e565b019160005b838110611fb75750505050565b6020908251611fc581610977565b60008152828451611fd581610992565b600081526000828201526000868201526000606082015281830152828601015201611faa565b6000198114610f605760010190565b9190811015611ed65760061b0190565b8051821015611ed65760209160051b010190565b90815180825260208080930193019160005b82811061204e575050505090565b835180516001600160601b0316865282015180516001600160a01b0390811687850152818401518116604080890191909152820151166060808801919091520151608086015260a09094019392810192600101612040565b6120be6040929594939560608352606083019061202e565b6001600160a01b0390951660208201520152565b6020815260406001600160801b0360206120f685518483870152606086019061202e565b9401511691015290565b6040906001600160801b03610cda9493168152816020820152019061202e565b60405160208101906121448161213685856120d2565b03601f1981018352826109e3565b51902061215b46600052600c602052604060002090565b540361222457600061217746600052600c602052604060002090565b556040514681527fc945d9e1f8095c0dea44c1e121710035a0e1825064e18e6e9d304e2cbf233c2090602090a180516121af816139b7565b600a546121da906020906121cb906001600160a01b0316610798565b9301516001600160801b031690565b90823b156101c057612206926000928360405180968195829463ad102f9b60e01b845260048401612100565b03925af180156104a6576122175750565b806107ec61052d9261095f565b60405163be364e3b60e01b8152600490fd5b90601f811161224457505050565b6000916000526020600020906020601f850160051c83019410612282575b601f0160051c01915b82811061227757505050565b81815560010161226b565b9092508290612262565b9092916001600160401b038111610972576122b1816122ab8454610ba4565b84612236565b6000601f82116001146122f25781906122e39394956000926122e7575b50508160011b916000199060031b1c19161790565b9055565b0135905038806122ce565b601f1982169461230784600052602060002090565b91805b878110612342575083600195969710612328575b505050811b019055565b0135600019600384901b60f8161c1916905538808061231e565b9092602060018192868601358155019401910161230a565b908060209392818452848401376000828201840152601f01601f1916010190565b929160609261ffff61239e9397969716855260806020860152608085019161235a565b9360208135916123ad83610a49565b6001600160801b03809316604086015201356123c881610a49565b16910152565b6040916000825260209260408484015260a0830182516040850152848301519460608080870152865180935260c086018260c08560051b8901019801946000925b85841061242a57505050505050506040608091015191015290565b90919293949598858060019260bf198c82030187528c5190856124696124596080855190808652850190610ca4565b8585015184820387860152610ca4565b9260ff89820151168984015281878060a01b03910151169101529b019401940192959493919061240f565b826014949392823701906001600160601b03199060601b1681520190565b91908260409103126101c0576020823592013590565b9495939490926001600160a01b0392909190337f000000000000000000000000ecc19e177d24551aa7ed6bc6fe566eca726cc8a98516148015612628575b15612616576116a661255591612529966040519788916020830193309185612494565b039661253d601f19988981018352826109e3565b5190209261ffff166000526003602052604060002090565b602081519101200361260e5761052d956125ec926125a5928116907f000000000000000000000000000000000000000000000000000000000000000016810361260857506000945b8101906124b2565b60408051602081019384526001600160a01b038716918101919091526060810187905290936125d89082608081016106e6565b51902091600052600c602052604060002090565b55600a54612602906001600160a01b0316610798565b90613e96565b9461259d565b505050505050565b604051631dd2188d60e31b8152600490fd5b5060015461263e906001600160a01b0316610798565b3314612506565b908160209103126101c05751610cda8161050f565b906020916020818303126101c0578051906001600160401b0382116101c0570181601f820112156101c05780519261269184610a1e565b936040936126a260405196876109e3565b81865260208087019260061b850101938185116101c057602001915b8483106126ce5750505050505090565b8386916126db8486611956565b8152019201916126be565b6020818303126101c0578051906001600160401b0382116101c0570181601f820112156101c0578051612718816115e7565b9261272660405194856109e3565b818452602082840101116101c057610cda9160208085019101610c81565b906020116101c05790602090565b359060208110612760575090565b6000199060200360031b1b1690565b60ff8116036101c057565b91908260409103126101c057602082356127938161276f565b92013590565b604051906127a682610977565b60606020838281520152565b9060209081835260608301908051916040848601528251809152836080860193019060005b81811061282b57505050820151926040601f198284030191015281808451928381520193019160005b82811061280e575050505090565b83516001600160601b031685529381019392810192600101612800565b8251855293850193918501916001016127d7565b604090610cda93928152816020820152019061202e565b9080601f830112156101c057602090823561287081610a1e565b9361287e60405195866109e3565b81855260208086019260051b8201019283116101c057602001905b8282106128a7575050505090565b8380916128b384610a35565b815201910190612899565b916060838303126101c05782356128d48161276f565b926020808201359360408301356001600160401b03938482116101c05701906040828203126101c0576040519361290a85610977565b82358181116101c057830182601f820112156101c05780359061292c82610a1e565b9161293a60405193846109e3565b808352868084019160051b830101918583116101c05787809101915b83831061297f57505050508552838301359081116101c0576129789201612856565b9082015290565b8235815291810191889101612956565b9080601f830112156101c057816020610cda93359101611602565b906080828203126101c05781356129c08161276f565b9260208301356129cf8161050f565b9260408101359260608201356001600160401b0381116101c057610cda920161298f565b519081151582036101c057565b91908260409103126101c057610cda60208351612a1c8161050f565b93016129f3565b610cda9392606092825260208201528160408201520190610ca4565b916060838303126101c0578235612a558161276f565b926020810135612a648161050f565b9260408201356001600160401b0381116101c057610cda920161298f565b906060610cda9260008152600060208201528160408201520190610ca4565b908160609103126101c0578035612ab78161276f565b91604060208301356127938161050f565b60ff612ae6612ae0612ada8585612744565b90612752565b60ff1690565b1660018103612c1f575080612b4e92612b00920190612aa1565b600b546001600160a01b039493509091604091859190612b21908316610798565b835163701c61ed60e11b8152919092166001600160a01b0316600482015293849190829081906024820190565b03915afa9283156104a657612ba193602093600091612bef575b50604051632df8a21160e11b81526001600160a01b03909116600482015260248101929092529092839190829060009082906044820190565b03927f000000000000000000000000e903f5a1d43d93407bcd11c771c03628539414d2165af180156104a657612bd45750565b612bec9060203d60201161191b5761190a81836109e3565b50565b612c11915060403d604011612c18575b612c0981836109e3565b810190612a00565b5038612b68565b503d612bff565b60028103612d535750612c3491810190612a3f565b600b546001600160a01b039283169350909190612c52908216610798565b6040805163701c61ed60e11b81526001600160a01b0386166004820152909490918583602481845afa80156104a657600093600091612d30575b5015612ccc575b50501691823b156101c0576000928392612cc1925194858094819363216f3c6b60e01b835260048301612a82565b03925af16122175750565b8551634c96a38960e01b81526001600160a01b03929092166004830152602090829060249082906000905af19081612d11575b50612d0a5750505050565b3880612c93565b612d299060203d6020116112af576112a081836109e3565b5038612cff565b9050612d4a919350863d8811612c1857612c0981836109e3565b92909238612c8c565b60038103612f015750612d68918101906129aa565b600b546001600160a01b039384169450909190612d86908416610798565b6040805163701c61ed60e11b81526001600160a01b038716600482015290959194918682602481895afa80156104a657600092600091612ede575b508751632df8a21160e11b81526001600160a01b03841660048201526024810186905296602091828960448160007f000000000000000000000000e903f5a1d43d93407bcd11c771c03628539414d28b165af19889156104a657600099612ebf575b5015612e59575b5050501690813b156101c05760008094612cc196519687958694859363216f3c6b60e01b855260048501612a23565b8851634c96a38960e01b81526001600160a01b039390931660048401528190839060249082906000905af19182612ea1575b5050612e9957505050505050565b388080612e2a565b81612eb792903d106112af576112a081836109e3565b503880612e8b565b612ed7919950833d851161191b5761190a81836109e3565b9738612e23565b9050612ef8919250873d8911612c1857612c0981836109e3565b91909138612dc1565b60048103612f845750612f16918101906128be565b9150612f2c46600052600c602052604060002090565b557f000000000000000000000000e903f5a1d43d93407bcd11c771c03628539414d26001600160a01b0316803b156101c057604051630e8f3bf560e31b815291600091839182908490829061220690600483016127b2565b600581036130695750612f999181019061277a565b919050612fa4612799565b7f000000000000000000000000e903f5a1d43d93407bcd11c771c03628539414d26001600160a01b031690813b156101c057612ffb6040518093818094630e8f3bf560e31b825260009687958692600483016127b2565b03925af180156104a657613056575b50600a54613020906001600160a01b0316610798565b613028611f67565b90803b156130525761220693948360405180968195829463ad102f9b60e01b84526004840161283f565b8280fd5b806107ec6130639261095f565b3861300a565b600714613074575050565b6130809181019061277a565b600a54909150613098906001600160a01b0316610798565b803b156101c057604051630ca3008d60e01b815260048101929092526000908290602490829084905af180156104a6576122175750565b604051906130dc82610992565b606080836000815260006020820152600060408201520152565b9060405161310381610977565b91546001600160801b038116835260801c6020830152565b9190811015611ed65760051b81013590603e19813603018212156101c0570190565b9291906040906040850160408652815180915260608601916020809101936000905b838210613173575050505060209150930152565b8551805186526020908101516001600160a01b031690860152948201949384019360019091019061315f565b90602082519201516001600160601b03199081811693601481106131c257505050565b60140360031b82901b16169150565b90604051916001600160601b03191660208301526014825261052d82610977565b903590605e19813603018212156101c0570190565b91908260409103126101c0576020825192015190565b80358252602081013560208301526040810135601e19823603018112156101c05701602081359101906001600160401b0381116101c05780360382136101c057606083816040610cda960152019161235a565b9261329b610cda959361ffff6132a9941686526001602087015260a0604087015260a0860190610ca4565b908482036060860152610ca4565b91608081840391015261321d565b91908201809211610f6057565b979461331b94613329979293610cda9b999561ffff61012096168c526001600160801b0380921660208d01521660408b015260018060a01b031660608a0152608089015260a08801528060c088015286019061321d565b9084820360e0860152610ca4565b91610100818403910152610ca4565b9193926133436130cf565b60405163c45a015560e01b81529093906020816004817f000000000000000000000000ecc19e177d24551aa7ed6bc6fe566eca726cc8a96001600160a01b03165afa80156104a6576133a59160009161386d575b506001600160a01b03168552565b8051946040850195865260005b8651811015613863576133c5818461201a565b51906134606133ea6133e284516000526002602052604060002090565b5461ffff1690565b926133f48461388c565b60608a015261341661341182516000526004602052604060002090565b6130f6565b60408201518a51602090613432906001600160a01b0316610798565b835160405163068bcd8d60e01b81526001600160801b03909116600482015295869190829081906024820190565b03915afa9384156104a657600494602091600091613846575b5060405163feb56b1560e01b815295869182906001600160a01b03165afa9081156104a657898b928f928e97600092613825575b50106137ad57509161358461357f60606134de613537958998976134d8602061356c9c01518d611e79565b9161311b565b966135788288017f37a28c62bfa8e4579bdc54985bb8380deeb34721706ffd1aac79b28b6a00d683815160408b01519061351d6040519283928361313d565b0390a151604089015160405198899160208301938461313d565b039761354b601f19998a81018352826109e3565b5190206040805160208101929092524690820152998a979088906060820190565b039081018852876109e3565b015161319f565b6131d1565b93604085896135b061359685806131f2565b8451630a51236960e01b81529a8b94859460048601613270565b03817f000000000000000000000000ecc19e177d24551aa7ed6bc6fe566eca726cc8a96001600160a01b03165afa9586156104a65760009661377b575b506020840180519096939084906001600160a01b031615613763575b5086516040860151613645917f000000000000000000000000ecc19e177d24551aa7ed6bc6fe566eca726cc8a9906001600160a01b0316614036565b604061366c602061365d86516001600160801b031690565b9501516001600160801b031690565b9501519061367a83806131f2565b967f000000000000000000000000ecc19e177d24551aa7ed6bc6fe566eca726cc8a96001600160a01b03163b156101c0576000976020956136d7946040519d8e9a8b998a996327efc43f60e21b8b52013593309260048b016132c4565b03917f000000000000000000000000ecc19e177d24551aa7ed6bc6fe566eca726cc8a96001600160a01b03165af19081156104a65760019361374a92613750575b50517f000000000000000000000000ecc19e177d24551aa7ed6bc6fe566eca726cc8a9906001600160a01b0316613f2e565b016133b2565b806107ec61375d9261095f565b38613718565b6137749194506040860151906132b7565b9238613609565b61379e91965060403d6040116137a6575b61379681836109e3565b810190613207565b5094386135ed565b503d61378c565b925050506001946121366137e26060806138209701519501515160405192839160208301919060206040840193600781520152565b613818610f398d60206138006137f9828901611e15565b9780611e1f565b919092019182519261381184611ffb565b9052611edb565b9330926138ca565b61374a565b61383f91925060203d60201161191b5761190a81836109e3565b90386134ad565b61385d9150823d84116112af576112a081836109e3565b38613479565b5095505050505050565b613886915060203d6020116112af576112a081836109e3565b38613397565b61ffff16908160005260036020526138a76040600020610bde565b918251156138b25750565b60249060405190639cd86f1760e01b82526004820152fd5b929493909291906001600160a01b0390811661397757807f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf6216924791843b156101c0576139499760009761ffff956122069361395c6040519c8d9b8c9a8b9962c5803160e81b8b521660048a015260c060248a015260c4890190610ca4565b60031993848983030160448a0152610ca4565b931660648601528960848601528483030160a4850152610ca4565b60405163653626cf60e01b8152600490fd5b816000190481118202158302156101c057020490565b600160601b8110156101c0576001600160601b031690565b6009546139cc906001600160a01b03166141fe565b906139e28251926020808095830101910161265a565b60005b8251811015613ab2576060846139fb838661201a565b5101510151468103613a11575b506001016139e5565b92909493600094855b8451811015613aa757613a2d818661201a565b51518614613a3d57600101613a1a565b90969294919550613a85613a6687613a576001948861201a565b5101516001600160a01b031690565b8780613a72878a61201a565b5101516001600160a01b03909216910152565b613a085760405163132b474b60e31b81526004810191909152602490fd5b0390fd5b509591939094613a85565b50505050565b60405190613ac5826109ad565b6000604083828152606060208201520152565b90613ae282610a1e565b604090613af260405191826109e3565b8381528093613b03601f1991610a1e565b019160009160005b848110613b19575050505050565b6020908351613b2781610992565b606080825286849180838501528188850152830152828501015201613b0b565b9190811015611ed65760051b0190565b908160209103126101c05751610cda8161276f565b6040519060008260075491613b8083610ba4565b80835292602090600190818116908115613c0c5750600114613bab575b505061052d925003836109e3565b91509260076000527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688936000925b828410613bf4575061052d9450505081016020013880613b9d565b85548885018301529485019487945092810192613bd9565b9150506020925061052d94915060ff191682840152151560051b8201013880613b9d565b60405190613c3d826109ad565b6040516006548391600081613c5184610ba4565b9182825260209460019086600182169182600014613cf8575050600114613c9b575b50613c80925003826109e3565b8252613c8a613b6c565b90820152604060ff60085416910152565b85915060066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f906000915b858310613ce0575050613c80935082010138613c73565b80548388018501528694508793909201918101613cc9565b60ff191685820152613c8095151560051b8501019250389150613c739050565b90613d21613ab8565b91602092604093808301356040830152468252613d48613d418480611e1f565b9050613ad8565b9281830193845260009260005b613d5f8380611e1f565b9050811015613e8d57613d84613d7f82613d798680611e1f565b90613b47565b611e15565b9084896001600160a01b03841680613e015750613df991613dec600195613ddc8694613dae613c30565b90613dc28183519784015193015160ff1690565b91613dcb610a04565b9687528d87015285019060ff169052565b6001600160a01b03166060830152565b8951906108ce838361201a565b505b01613d55565b905060049150613e10816140cc565b87613e1a8361418a565b928d519485809263313ce56760e01b82525afa9182156104a657600195613ddc86948f613dec94613e58988f8f9094613e5e575b5050613dcb610a04565b50613dfb565b613e7e929450803d10613e86575b613e7681836109e3565b810190613b57565b91388e613e4e565b503d613e6c565b50955050505050565b8215613f29576001600160a01b03818116613ed557505060008080613ebd9481945af11590565b613ec357565b604051633d2cec6f60e21b8152600490fd5b60209260008093613f11966044946040519463a9059cbb60e01b865216600485015260248401525af1600051600114601f3d11163d1517161590565b613f1757565b604051633c9fd93960e21b8152600490fd5b505050565b6001600160a01b031680156116c05760405163095ea7b360e01b602082018181526001600160a01b0385166024840152600060448401819052919492939290918085606481015b0393613f89601f19958681018952886109e3565b86519082875af1613f9861407e565b81614007575b5080613ffd575b15613fb2575b5050505050565b60405160208101959095526001600160a01b0316602485015260006044850152613ff393613fee91613fe89082606481016106e6565b82614268565b614268565b3880808080613fab565b50823b1515613fa5565b805180159250821561401c575b505038613f9e565b61402f9250602080918301019101614254565b3880614014565b6001600160a01b03168015613f295760405163095ea7b360e01b602082018181526001600160a01b038516602484015260448301959095529390926000808560648101613f75565b3d156140a9573d9061408f826115e7565b9161409d60405193846109e3565b82523d6000602084013e565b606090565b8015610f60576000190190565b908151811015611ed6570160200190565b6000809160405160208101906306fdde0360e01b8252600481526140ef81610977565b51915afa906140fc61407e565b9115614178578151602081036141655750602082815b6141195752565b9061414d61414061413261412c84611e6a565b856140bb565b516001600160f81b03191690565b6001600160f81b03191690565b6141615761415a906140ae565b9081614112565b9052565b91602080610cda939483010191016126e6565b6040516360d806dd60e11b8152600490fd5b6000809160405160208101906395d89b4160e01b8252600481526141ad81610977565b51915afa906141ba61407e565b9115614178578151602081036141655750602082815b6141d75752565b906141ea61414061413261412c84611e6a565b614161576141f7906140ae565b90816141d0565b90813b8015614245578060011161424557600019016001198082101561423e57505b600160405193601f19603f840116850160405282855260208501903c565b9050614220565b509050604051611f73816109c8565b908160209103126101c057610cda906129f3565b6040516142c6916001600160a01b031661428182610977565b6000806020958685527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656487860152868151910182855af16142c061407e565b9161434e565b805190828215928315614336575b505050156142df5750565b6084906040519062461bcd60e51b82526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152fd5b6143469350820181019101614254565b3882816142d4565b919290156143b05750815115614362575090565b3b1561436b5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156143c35750805190602001fd5b60405162461bcd60e51b815260206004820152908190613aa3906024830190610ca456
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000de4d377d8a8d455330edd7c4eb5b284ada1113d8000000000000000000000000ecc19e177d24551aa7ed6bc6fe566eca726cc8a90000000000000000000000003c2269811836af69497e5f486a85d7316753cf62000000000000000000000000e903f5a1d43d93407bcd11c771c03628539414d2000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000007506f6c79676f6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054d41544943000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : owner (address): 0xdE4D377D8A8d455330edD7C4EB5b284ADA1113d8
Arg [1] : _stargateComposer (address): 0xeCc19E177d24551aA7ed6Bc6FE566eCa726CC8a9
Arg [2] : _endpoint (address): 0x3c2269811836af69497E5F486A85D7316753cf62
Arg [3] : _vault (address): 0xE903F5a1D43d93407Bcd11c771c03628539414d2
Arg [4] : _homeEid (uint16): 110
Arg [5] : _sgETH (address): 0x0000000000000000000000000000000000000000
Arg [6] : _nativeInfo (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
-----Encoded View---------------
14 Constructor Arguments found :
Arg [0] : 000000000000000000000000de4d377d8a8d455330edd7c4eb5b284ada1113d8
Arg [1] : 000000000000000000000000ecc19e177d24551aa7ed6bc6fe566eca726cc8a9
Arg [2] : 0000000000000000000000003c2269811836af69497e5f486a85d7316753cf62
Arg [3] : 000000000000000000000000e903f5a1d43d93407bcd11c771c03628539414d2
Arg [4] : 000000000000000000000000000000000000000000000000000000000000006e
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [6] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [8] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000012
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [11] : 506f6c79676f6e00000000000000000000000000000000000000000000000000
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [13] : 4d41544943000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.