More Info
Private Name Tags
ContractCreator
Latest 13 from a total of 13 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Rebalance And Fi... | 15781987 | 635 days ago | IN | 0 ETH | 0.0053367 | ||||
Rebalance And Fi... | 15767014 | 637 days ago | IN | 0 ETH | 0.00373015 | ||||
Rebalance And Fi... | 15713687 | 645 days ago | IN | 0 ETH | 0.01210133 | ||||
Rebalance And Fi... | 15691492 | 648 days ago | IN | 0 ETH | 0.00426539 | ||||
Rebalance And Fi... | 15683052 | 649 days ago | IN | 0 ETH | 0.01093505 | ||||
Rebalance And Fi... | 15675716 | 650 days ago | IN | 0 ETH | 0.00508122 | ||||
Rebalance And Fi... | 15670761 | 651 days ago | IN | 0 ETH | 0.00455868 | ||||
Rebalance And Fi... | 15659336 | 652 days ago | IN | 0 ETH | 0.0015698 | ||||
Rebalance And Fi... | 15648315 | 654 days ago | IN | 0 ETH | 0.00426251 | ||||
Rebalance And Fi... | 15648310 | 654 days ago | IN | 0 ETH | 0.00499677 | ||||
Rebalance And Fi... | 15640301 | 655 days ago | IN | 0 ETH | 0.0073333 | ||||
Rebalance And Fi... | 15633103 | 656 days ago | IN | 0 ETH | 0.00379204 | ||||
0x61012060 | 15582793 | 663 days ago | IN | Create: UniswapDCABridge | 0 ETH | 0.06443824 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
16967467 | 469 days ago | 0.98877328 ETH | ||||
16967467 | 469 days ago | 0.98877328 ETH | ||||
16886410 | 481 days ago | 1.14831567 ETH | ||||
16886410 | 481 days ago | 1.14831567 ETH | ||||
16883289 | 481 days ago | 0.00038 ETH | ||||
16883289 | 481 days ago | 0.00038 ETH | ||||
16871876 | 483 days ago | 0.05846 ETH | ||||
16871876 | 483 days ago | 0.05846 ETH | ||||
16869274 | 483 days ago | 0.047775 ETH | ||||
16869274 | 483 days ago | 0.047775 ETH | ||||
16857668 | 485 days ago | 10.181478 ETH | ||||
16857668 | 485 days ago | 10.181478 ETH | ||||
16853856 | 485 days ago | 2.5244728 ETH | ||||
16853856 | 485 days ago | 2.5244728 ETH | ||||
16853856 | 485 days ago | 1.02731719 ETH | ||||
16853856 | 485 days ago | 1.02731719 ETH | ||||
16838762 | 487 days ago | 3.6635447 ETH | ||||
16838762 | 487 days ago | 3.6635447 ETH | ||||
16827054 | 489 days ago | 0.151196 ETH | ||||
16827054 | 489 days ago | 0.151196 ETH | ||||
16819659 | 490 days ago | 1.98253301 ETH | ||||
16819659 | 490 days ago | 1.98253301 ETH | ||||
16819659 | 490 days ago | 8.4556439 ETH | ||||
16819659 | 490 days ago | 8.4556439 ETH | ||||
16811524 | 491 days ago | 0.268017 ETH |
Loading...
Loading
Contract Name:
UniswapDCABridge
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 100000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache-2.0 // Copyright 2022 Aztec. pragma solidity >=0.8.4; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {IWETH} from "../../interfaces/IWETH.sol"; import {IChainlinkOracle} from "../../interfaces/chainlink/IChainlinkOracle.sol"; import {ISwapRouter} from "../../interfaces/uniswapv3/ISwapRouter.sol"; import {BiDCABridge} from "./BiDCABridge.sol"; /** * @notice Initial implementation of the BiDCA bridge using Uniswap as the DEX and Chainlink as oracle. * The bridge is using DAI and WETH for A and B with a Chainlink oracle to get prices. * The bridge allows users to force a rebalance through Uniswap pools. * The forced rebalance will: * 1. rebalance internally in the ticks, as the BiDCABridge, * 2. rebalance cross-ticks, e.g., excess from the individual ticks are matched, * 3. swap any remaining excess using Uniswap, and rebalance with the returned assets * @dev The slippage + path is immutable, so low liquidity in Uniswap might block the `rebalanceAndfillUniswap` flow. * @author Lasse Herskind (LHerskind on GitHub). */ contract UniswapDCABridge is BiDCABridge { using SafeERC20 for IERC20; error NegativePrice(); address internal constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; address internal constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; uint160 internal constant SQRT_PRICE_LIMIT_X96 = 1461446703485210103287273052203988822378723970341; ISwapRouter public constant UNI_ROUTER = ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564); uint256 public constant SLIPPAGE = 100; // Basis points IChainlinkOracle public constant ORACLE = IChainlinkOracle(0x773616E4d11A78F511299002da57A0a94577F1f4); constructor( address _rollupProcessor, uint256 _tickSize, uint256 _fee ) BiDCABridge(_rollupProcessor, DAI, address(WETH), _tickSize, _fee) { IERC20(DAI).safeApprove(address(UNI_ROUTER), type(uint256).max); IERC20(address(WETH)).safeApprove(address(UNI_ROUTER), type(uint256).max); } function rebalanceAndFillUniswap() public returns (int256, int256) { rebalanceAndFillUniswap(type(uint256).max); } /** * @notice Rebalances within ticks, then across ticks, and finally, take the remaining funds to uniswap * where it is traded for the opposite, and used to rebalance completely * @dev Uses a specific path for the assets to do the swap * @dev Slippage protection through the chainlink oracle, as a base price * @dev Can be quite gas intensive as it will loop multiple times over the ticks to fill orders. * @return aFlow The flow of token A * @return bFlow The flow of token B */ function rebalanceAndFillUniswap(uint256 _upperTick) public returns (int256, int256) { uint256 oraclePrice = getPrice(); (int256 aFlow, int256 bFlow, uint256 a, uint256 b) = _rebalanceAndFill(0, 0, oraclePrice, _upperTick, true); // If we have available A and B, we can do internal rebalancing across ticks with these values. if (a > 0 && b > 0) { (aFlow, bFlow, a, b) = _rebalanceAndFill(a, b, oraclePrice, _upperTick, true); } if (a > 0) { // Trade all A to B using uniswap. uint256 bOffer = UNI_ROUTER.exactInput( ISwapRouter.ExactInputParams({ path: abi.encodePacked(ASSET_A, uint24(100), USDC, uint24(500), ASSET_B), recipient: address(this), deadline: block.timestamp, amountIn: a, amountOutMinimum: (denominateAssetAInB(a, oraclePrice, false) * (10000 - SLIPPAGE)) / 10000 }) ); // Rounding DOWN ensures that B received / price >= A available uint256 price = (bOffer * 1e18) / a; (aFlow, bFlow, , ) = _rebalanceAndFill(0, bOffer, price, _upperTick, true); } if (b > 0) { // Trade all B to A using uniswap. uint256 aOffer = UNI_ROUTER.exactInput( ISwapRouter.ExactInputParams({ path: abi.encodePacked(ASSET_B, uint24(500), USDC, uint24(100), ASSET_A), recipient: address(this), deadline: block.timestamp, amountIn: b, amountOutMinimum: (denominateAssetBInA(b, oraclePrice, false) * (10000 - SLIPPAGE)) / 10000 }) ); // Rounding UP to ensure that A received * price >= B available uint256 price = (b * 1e18 + aOffer - 1) / aOffer; (aFlow, bFlow, , ) = _rebalanceAndFill(aOffer, 0, price, _upperTick, true); } return (aFlow, bFlow); } /** * @notice Fetch the price from the chainlink oracle. * @dev Reverts if the price is stale or negative * @return Price */ function getPrice() public virtual override(BiDCABridge) returns (uint256) { (, int256 answer, , , ) = ORACLE.latestRoundData(); if (answer < 0) { revert NegativePrice(); } return uint256(answer); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-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; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } 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"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: Apache-2.0 // Copyright 2022 Aztec. pragma solidity >=0.8.4; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IWETH is IERC20 { function deposit() external payable; function withdraw(uint256 amount) external; }
// SPDX-License-Identifier: Apache-2.0 // Copyright 2022 Aztec. pragma solidity >=0.8.4; interface IChainlinkOracle { function latestRoundData() external view returns ( uint80, int256, uint256, uint256, uint80 ); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.4; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface ISwapRouter { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: Apache-2.0 // Copyright 2022 Aztec. pragma solidity >=0.8.4; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {IRollupProcessor} from "../../aztec/interfaces/IRollupProcessor.sol"; import {BridgeBase} from "../base/BridgeBase.sol"; import {ErrorLib} from "../base/ErrorLib.sol"; import {AztecTypes} from "../../aztec/libraries/AztecTypes.sol"; import {IWETH} from "../../interfaces/IWETH.sol"; import {SafeCastLib} from "./SafeCastLib.sol"; /** * @notice Initial abstract implementation of "Dollar" Cost Averaging. * The bridge implements a bidirectional dollar cost averaging protocol, * allowing users to go either direction between two tokens A and B. * The "order" is executed over a period of time, instead of all at once. * For Eth and Dai, this allows the user to sell Dai to buy Eth over X days, and vice versa. * The timeperiod is divided into ticks, with each tick keeping track of the funds that should be traded in that tick. * As well as the price, and how much have been received in return. * To "balance" the scheme, an external party can buy assets at the orace-price (no slippage). * The amount that can be bought by the external party, depends on the ticks and how much can be matched internally. * As part of the balancing act, each tick will match the A and B holdings it has to sell, using the oracle price * (or infer price from prior price and current price). * The excess from this internal matching is then sold off to the caller at oracle price, to match his offer. * The rebalancing is expected to be done by arbitrageurs when prices deviate sufficiently between the oracle and dexes. * The finalise function is incentivised by giving part of the traded value to the `tx.origin` (msg.sender always rollup processor). * Extensions to this bridge can be made such that the external party can be Uniswap or another dex. * An extension should also define the oracle to be used for the price. * @dev Built for assets with 18 decimals precision * @dev A contract that inherits must handle the case for forcing a swap through a DEX. * @author Lasse Herskind (LHerskind on GitHub). */ abstract contract BiDCABridge is BridgeBase { using SafeERC20 for IERC20; using SafeCastLib for uint256; using SafeCastLib for uint128; error FeeTooLarge(); error PositionAlreadyExists(); error NoDeposits(); /** * @notice A struct used in-memory to get around stack-to-deep errors * @member currentPrice Current oracle price * @member earliestTickWithAvailableA Earliest tick with available asset A * @member earliestTickWithAvailableB Earliest tick with available asset B * @member offerAInB Amount of asset B that is offered to be bought at the current price for A * @member offerBInA Amount of asset A that is offered to be bought at the current price for B * @member protocolSoldA Amount of asset A the bridge sold * @member protocolSoldB Amount of asset B the bridge sold * @member protocolBoughtA Amount of asset A the bridge bought * @member protocolBoughtB Amount of asset B the bridge bought * @member lastUsedPrice Last used price during rebalancing (cache in case new price won't be available) * @member lastUsedPriceTime Time at which last used price was set * @member availableA The amount of asset A that is available * @member availableB The amount of asset B that is available */ struct RebalanceValues { uint256 currentPrice; uint256 earliestTickWithAvailableA; uint256 earliestTickWithAvailableB; uint256 offerAInB; uint256 offerBInA; uint256 protocolSoldA; uint256 protocolSoldB; uint256 protocolBoughtA; uint256 protocolBoughtB; uint256 lastUsedPrice; uint256 lastUsedPriceTime; uint256 availableA; uint256 availableB; } /** * @notice A struct representing 1 DCA position * @member amount Amount of asset A or B to be sold * @member start Index of the first tick this position touches * @member end Index of the last tick this position touches * @member aToB True if A is being sold to B, false otherwise */ struct DCA { uint128 amount; uint32 start; uint32 end; bool aToB; } /** * @notice A struct defining one direction in a tick * @member sold Amount of asset sold * @member bought Amount of asset bought */ struct SubTick { uint128 sold; uint128 bought; } /** * @notice A container for Tick related data * @member availableA Amount of A available in a tick for sale * @member availableB Amount of B available in a tick for sale * @member poke A value used only to initialize a storage slot * @member aToBSubTick A struct capturing info of A to B trades * @member aToBSubTick A struct capturing info of B to A trades * @member priceAToB A price of A denominated in B * @member priceTime A time at which price was last updated */ struct Tick { uint120 availableA; uint120 availableB; uint16 poke; SubTick aToBSubTick; SubTick bToASubTick; uint128 priceOfAInB; uint32 priceTime; } IWETH internal constant WETH = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); uint256 public constant FEE_DIVISOR = 10000; // The assets that are DCAed between IERC20 public immutable ASSET_A; IERC20 public immutable ASSET_B; // The timespan that a tick covers uint256 public immutable TICK_SIZE; uint256 public immutable FEE; // The earliest tick where we had available A or B respectively. uint32 public earliestTickWithAvailableA; uint32 public earliestTickWithAvailableB; // tick id => Tick. mapping(uint256 => Tick) public ticks; // nonce => DCA mapping(uint256 => DCA) public dcas; /** * @notice Constructor * @param _rollupProcessor The address of the rollup processor for the bridge * @param _assetA The address of asset A * @param _assetB The address of asset B * @param _tickSize The time-span that each tick covers in seconds * @dev Smaller _tickSizes will increase looping and gas costs */ constructor( address _rollupProcessor, address _assetA, address _assetB, uint256 _tickSize, uint256 _fee ) BridgeBase(_rollupProcessor) { ASSET_A = IERC20(_assetA); ASSET_B = IERC20(_assetB); TICK_SIZE = _tickSize; IERC20(_assetA).safeApprove(_rollupProcessor, type(uint256).max); IERC20(_assetB).safeApprove(_rollupProcessor, type(uint256).max); if (_fee > FEE_DIVISOR) { revert FeeTooLarge(); } FEE = _fee; } receive() external payable {} /** * @notice Helper used to poke storage from next tick and `_ticks` forwards * @param _numTicks The number of ticks to poke */ function pokeNextTicks(uint256 _numTicks) external { pokeTicks(_nextTick(block.timestamp), _numTicks); } /** * @notice Helper used to poke storage of ticks to make deposits more consistent in gas usage * @dev First sstore is very expensive, so by doing it as this, we can prepare it before deposit * @param _startTick The first tick to poke * @param _numTicks The number of ticks to poke */ function pokeTicks(uint256 _startTick, uint256 _numTicks) public { for (uint256 i = _startTick; i < _startTick + _numTicks; i++) { ticks[i].poke++; } } /** * @notice Rebalances ticks using internal values first, then with externally provided assets. * Ticks are balanced internally using the price at the specific tick (either stored in tick, or interpolated). * Leftover assets are sold using current price to fill as much of the offer as possible. * @param _offerA The amount of asset A that is offered for sale to the bridge * @param _offerB The amount of asset B that is offered for sale to the bridge * @return flowA The flow of asset A from the bridge POV, e.g., >0 = buying of tokens, <0 = selling tokens * @return flowB The flow of asset B from the bridge POV, e.g., >0 = buying of tokens, <0 = selling tokens */ function rebalanceAndFill(uint256 _offerA, uint256 _offerB) public returns (int256, int256) { return rebalanceAndFill(_offerA, _offerB, type(uint256).max); } /** * @notice Rebalances ticks using internal values first, then with externally provided assets. * Ticks are balanced internally using the price at the specific tick (either stored in tick, or interpolated). * Leftover assets are sold using current price to fill as much of the offer as possible. * @param _offerA The amount of asset A that is offered for sale to the bridge * @param _offerB The amount of asset B that is offered for sale to the bridge * @param _upperTick The upper limit for ticks (useful gas-capped rebalancing) * @return flowA The flow of asset A from the bridge POV, e.g., >0 = buying of tokens, <0 = selling tokens * @return flowB The flow of asset B from the bridge POV, e.g., >0 = buying of tokens, <0 = selling tokens */ function rebalanceAndFill( uint256 _offerA, uint256 _offerB, uint256 _upperTick ) public returns (int256, int256) { (int256 flowA, int256 flowB, , ) = _rebalanceAndFill(_offerA, _offerB, getPrice(), _upperTick, false); if (flowA > 0) { ASSET_A.safeTransferFrom(msg.sender, address(this), uint256(flowA)); } else if (flowA < 0) { ASSET_A.safeTransfer(msg.sender, uint256(-flowA)); } if (flowB > 0) { ASSET_B.safeTransferFrom(msg.sender, address(this), uint256(flowB)); } else if (flowB < 0) { ASSET_B.safeTransfer(msg.sender, uint256(-flowB)); } return (flowA, flowB); } /** * @notice Function to create DCA position from `_inputAssetA` to `_outputAssetA` over `_ticks` ticks. * @param _inputAssetA The asset to be sold * @param _outputAssetA The asset to be bought * @param _inputValue The value of `_inputAssetA` to be sold * @param _interactionNonce The unique identifier for the interaction, used to identify the DCA position * @param _numTicks The auxdata, passing the number of ticks the position should run * @return Will always return 0 assets, and isAsync = true. */ function convert( AztecTypes.AztecAsset calldata _inputAssetA, AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata _outputAssetA, AztecTypes.AztecAsset calldata, uint256 _inputValue, uint256 _interactionNonce, uint64 _numTicks, address ) external payable override(BridgeBase) onlyRollup returns ( uint256, uint256, bool ) { address inputAssetAddress = _inputAssetA.erc20Address; address outputAssetAddress = _outputAssetA.erc20Address; if (_inputAssetA.assetType == AztecTypes.AztecAssetType.ETH) { WETH.deposit{value: _inputValue}(); inputAssetAddress = address(WETH); } if (_outputAssetA.assetType == AztecTypes.AztecAssetType.ETH) { outputAssetAddress = address(WETH); } if (inputAssetAddress != address(ASSET_A) && inputAssetAddress != address(ASSET_B)) { revert ErrorLib.InvalidInputA(); } bool aToB = inputAssetAddress == address(ASSET_A); if (outputAssetAddress != (aToB ? address(ASSET_B) : address(ASSET_A))) { revert ErrorLib.InvalidOutputA(); } if (dcas[_interactionNonce].start != 0) { revert PositionAlreadyExists(); } _deposit(_interactionNonce, _inputValue, _numTicks, aToB); return (0, 0, true); } /** * @notice Function used to close a completed DCA position * @param _outputAssetA The asset bought with the DCA position * @param _interactionNonce The identifier for the DCA position * @return outputValueA The amount of assets bought * @return interactionComplete True if the interaction is completed and can be executed, false otherwise */ function finalise( AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata _outputAssetA, AztecTypes.AztecAsset calldata, uint256 _interactionNonce, uint64 ) external payable virtual override(BridgeBase) onlyRollup returns ( uint256 outputValueA, uint256, bool interactionComplete ) { uint256 accumulated; (accumulated, interactionComplete) = getAccumulated(_interactionNonce); if (interactionComplete) { bool toEth; address outputAssetAddress = _outputAssetA.erc20Address; if (_outputAssetA.assetType == AztecTypes.AztecAssetType.ETH) { toEth = true; outputAssetAddress = address(WETH); } if (outputAssetAddress != (dcas[_interactionNonce].aToB ? address(ASSET_B) : address(ASSET_A))) { revert ErrorLib.InvalidOutputA(); } uint256 incentive; if (FEE > 0) { incentive = (accumulated * FEE) / FEE_DIVISOR; } outputValueA = accumulated - incentive; delete dcas[_interactionNonce]; if (toEth) { WETH.withdraw(outputValueA); IRollupProcessor(ROLLUP_PROCESSOR).receiveEthFromBridge{value: outputValueA}(_interactionNonce); } if (incentive > 0) { // Cannot use the `msg.sender` as that would simply be the rollup. IERC20(outputAssetAddress).safeTransfer(tx.origin, incentive); } } } /** * @notice The brice of A in B, e.g., 10 would mean 1 A = 10 B * @return priceAToB measured with precision 1e18 */ function getPrice() public virtual returns (uint256); /** * @notice Computes the value of `_amount` A tokens in B tokens * @param _amount The amount of A tokens * @param _priceAToB The price of A tokens in B * @param _roundUp Flag to round up, if true rounding up, otherwise rounding down */ function denominateAssetAInB( uint256 _amount, uint256 _priceAToB, bool _roundUp ) public pure returns (uint256) { if (_roundUp) { return (_amount * _priceAToB + 1e18 - 1) / 1e18; } return (_amount * _priceAToB) / 1e18; } /** * @notice Computes the value of `_amount` A tokens in B tokens * @param _amount The amount of A tokens * @param _priceAToB The price of A tokens in B * @param _roundUp Flag to round up, if true rounding up, otherwise rounding down */ function denominateAssetBInA( uint256 _amount, uint256 _priceAToB, bool _roundUp ) public pure returns (uint256) { if (_roundUp) { return (_amount * 1e18 + _priceAToB - 1) / _priceAToB; } return (_amount * 1e18) / _priceAToB; } /** * @notice Helper to fetch the tick at `_tick` * @param _tick The tick to fetch * @return The Tick structure */ function getTick(uint256 _tick) public view returns (Tick memory) { return ticks[_tick]; } /** * @notice Helper to fetch the DCA at `_nonce` * @param _nonce The DCA to fetch * @return The DCA structure */ function getDCA(uint256 _nonce) public view returns (DCA memory) { return dcas[_nonce]; } /** * @notice Helper to compute the amount of available tokens (not taking rebalancing into account) * @return availableA Available amount of token A * @return availableB Available amount of token B */ function getAvailable() public view returns (uint256 availableA, uint256 availableB) { uint256 start = _earliestUsedTick(earliestTickWithAvailableA, earliestTickWithAvailableB); uint256 lastTick = block.timestamp / TICK_SIZE; for (uint256 i = start; i <= lastTick; i++) { availableA += ticks[i].availableA; availableB += ticks[i].availableB; } } /** * @notice Helper to get the amount of accumulated tokens for a specific DCA (and a flag for finalisation readiness) * @param _nonce The DCA to fetch * @return accumulated The amount of assets accumulated * @return ready A flag that is true if the accumulation has completed, false otherwise */ function getAccumulated(uint256 _nonce) public view returns (uint256 accumulated, bool ready) { DCA memory dca = dcas[_nonce]; uint256 start = dca.start; uint256 end = dca.end; uint256 tickAmount = dca.amount / (end - start); bool aToB = dca.aToB; ready = true; for (uint256 i = start; i < end; i++) { Tick storage tick = ticks[i]; (uint256 available, uint256 sold, uint256 bought) = aToB ? (tick.availableA, tick.aToBSubTick.sold, tick.aToBSubTick.bought) : (tick.availableB, tick.bToASubTick.sold, tick.bToASubTick.bought); ready = ready && available == 0 && sold > 0; accumulated += sold == 0 ? 0 : (bought * tickAmount) / (sold + available); } } /** * @notice Computes the next tick * @dev Note that the return value can be the current tick if we are exactly at the threshold * @return The next tick */ function _nextTick(uint256 _time) internal view returns (uint256) { return ((_time + TICK_SIZE - 1) / TICK_SIZE); } function _min(uint256 _a, uint256 _b) internal pure returns (uint256) { return _a > _b ? _b : _a; } /** * @notice Create a new DCA position starting at next tick and accumulates the available assets to the future ticks. * @param _nonce The interaction nonce * @param _amount The amount of assets deposited * @param _ticks The number of ticks that the position span * @param _aToB A flag that is true if input asset is assetA and false otherwise. */ function _deposit( uint256 _nonce, uint256 _amount, uint256 _ticks, bool _aToB ) internal { uint256 nextTick = _nextTick(block.timestamp); if (_aToB && earliestTickWithAvailableA == 0) { earliestTickWithAvailableA = nextTick.toU32(); } if (!_aToB && earliestTickWithAvailableB == 0) { earliestTickWithAvailableB = nextTick.toU32(); } // Update prices of last tick, might be 1 second in the past. ticks[nextTick - 1].priceOfAInB = getPrice().toU128(); ticks[nextTick - 1].priceTime = block.timestamp.toU32(); uint256 tickAmount = _amount / _ticks; for (uint256 i = nextTick; i < nextTick + _ticks; i++) { if (_aToB) { ticks[i].availableA += tickAmount.toU120(); } else { ticks[i].availableB += tickAmount.toU120(); } } dcas[_nonce] = DCA({ amount: _amount.toU128(), start: nextTick.toU32(), end: (nextTick + _ticks).toU32(), aToB: _aToB }); } /** * @notice Rebalances ticks using internal values first, then with externally provided assets. * Ticks are balanced internally using the price at the specific tick (either stored in tick, or interpolated). * Leftover assets are sold using current price to fill as much of the offer as possible. * @param _offerA The amount of asset A that is offered for sale to the bridge * @param _offerB The amount of asset B that is offered for sale to the bridge * @param _currentPrice Current oracle price * @param _self A flag that is true if rebalancing with self, e.g., swapping available funds with dex and rebalancing, and false otherwise * @param _upperTick A upper limit for the ticks, useful for gas-capped execution * @return flowA The flow of asset A from the bridge POV, e.g., >0 = buying of tokens, <0 = selling tokens * @return flowB The flow of asset B from the bridge POV, e.g., >0 = buying of tokens, <0 = selling tokens * @return availableA The amount of asset A that is available after the rebalancing * @return availableB The amount of asset B that is available after the rebalancing */ function _rebalanceAndFill( uint256 _offerA, uint256 _offerB, uint256 _currentPrice, uint256 _upperTick, bool _self ) internal returns ( int256, int256, uint256, uint256 ) { RebalanceValues memory vars; vars.currentPrice = _currentPrice; // Cache and use earliest ticks with available funds vars.earliestTickWithAvailableA = earliestTickWithAvailableA; vars.earliestTickWithAvailableB = earliestTickWithAvailableB; uint256 earliestTick = _earliestUsedTick(vars.earliestTickWithAvailableA, vars.earliestTickWithAvailableB); // Cache last used price for use in case we don't have a fresh price. vars.lastUsedPrice = ticks[earliestTick].priceOfAInB; vars.lastUsedPriceTime = ticks[earliestTick].priceTime; if (vars.lastUsedPrice == 0) { uint256 lookBack = earliestTick; while (vars.lastUsedPrice == 0) { lookBack--; vars.lastUsedPrice = ticks[lookBack].priceOfAInB; vars.lastUsedPriceTime = ticks[lookBack].priceTime; } } // Compute the amount of B that is offered to be bought at current price for A. Round down vars.offerAInB = denominateAssetAInB(_offerA, vars.currentPrice, false); // Compute the amount of A that is offered to be bought at current price for B. Round down vars.offerBInA = denominateAssetBInA(_offerB, vars.currentPrice, false); uint256 nextTick = _nextTick(block.timestamp); // Update the latest tick, might be 1 second in the past. ticks[nextTick - 1].priceOfAInB = vars.currentPrice.toU128(); ticks[nextTick - 1].priceTime = block.timestamp.toU32(); for (uint256 i = earliestTick; i < _min(nextTick, _upperTick); i++) { // Load a cache Tick memory tick = ticks[i]; _rebalanceTickInternally(vars, tick, i); _useAOffer(vars, tick, _self); _useBOffer(vars, tick, _self); // If no more available and earliest is current tick, increment tick. if (tick.availableA == 0 && vars.earliestTickWithAvailableA == i) { vars.earliestTickWithAvailableA += 1; } if (tick.availableB == 0 && vars.earliestTickWithAvailableB == i) { vars.earliestTickWithAvailableB += 1; } // Add the leftover A and B from the tick to total available vars.availableA += tick.availableA; vars.availableB += tick.availableB; // Update the storage ticks[i] = tick; } if (vars.earliestTickWithAvailableA > earliestTickWithAvailableA) { earliestTickWithAvailableA = vars.earliestTickWithAvailableA.toU32(); } if (vars.earliestTickWithAvailableB > earliestTickWithAvailableB) { earliestTickWithAvailableB = vars.earliestTickWithAvailableB.toU32(); } // Compute flow of tokens, from the POV of this contract, e.g., >0 is inflow, <0 outflow int256 flowA = int256(vars.protocolBoughtA) - int256(vars.protocolSoldA); int256 flowB = int256(vars.protocolBoughtB) - int256(vars.protocolSoldB); return (flowA, flowB, vars.availableA, vars.availableB); } /** * @notice Perform internal rebalancing of a single tick using available balances * @dev Heavily uses that internal functions are passing reference to memory structures * */ function _rebalanceTickInternally( RebalanceValues memory _vars, Tick memory _tick, uint256 _tickId ) internal view { // Only perform internal rebalance if we have both assets available, otherwise nothing to rebalance if (_tick.availableA > 0 && _tick.availableB > 0) { uint256 price = _tick.priceOfAInB; // If a price is stored at tick, update the last used price and timestamp. Otherwise interpolate. if (price > 0) { _vars.lastUsedPrice = price; _vars.lastUsedPriceTime = _tick.priceTime; } else { int256 slope = (int256(_vars.currentPrice) - int256(_vars.lastUsedPrice)) / int256(block.timestamp - _vars.lastUsedPriceTime); // lastUsedPriceTime will always be an earlier tick than this. uint256 dt = _tickId * TICK_SIZE + TICK_SIZE / 2 - _vars.lastUsedPriceTime; int256 _price = int256(_vars.lastUsedPrice) + slope * int256(dt); if (_price <= 0) { price = 0; } else { price = uint256(_price); } } // To compare we need same basis. Compute value of the available A in base B. Round down uint128 availableADenominatedInB = denominateAssetAInB(_tick.availableA, price, false).toU128(); // If more value in A than B, we can use all available B. Otherwise, use all available A if (availableADenominatedInB > _tick.availableB) { // The value of all available B in asset A. Round down uint128 availableBDenominatedInA = denominateAssetBInA(_tick.availableB, price, false).toU128(); // Update Asset A _tick.aToBSubTick.bought += _tick.availableB; _tick.aToBSubTick.sold += availableBDenominatedInA; // Update Asset B _tick.bToASubTick.bought += availableBDenominatedInA; _tick.bToASubTick.sold += _tick.availableB; // Update available values _tick.availableA -= availableBDenominatedInA.toU120(); _tick.availableB = 0; } else { // We got more B than A, fill everything in A and part of B // Update Asset B _tick.bToASubTick.bought += _tick.availableA; _tick.bToASubTick.sold += availableADenominatedInB; // Update Asset A _tick.aToBSubTick.bought += availableADenominatedInB; _tick.aToBSubTick.sold += _tick.availableA; // Update available values _tick.availableA = 0; _tick.availableB -= availableADenominatedInB.toU120(); } } } /** * @notice Fills as much of the A offered as possible * @dev Heavily uses that internal functions are passing reference to memory structures * @param _self True if buying from "self" false otherwise. */ function _useAOffer( RebalanceValues memory _vars, Tick memory _tick, bool _self ) internal pure { if (_vars.offerAInB > 0 && _tick.availableB > 0) { uint128 amountBSold = _vars.offerAInB.toU128(); // We cannot buy more than available if (_vars.offerAInB > _tick.availableB) { amountBSold = _tick.availableB; } // Underpays actual price if self, otherwise overpay (to not mess rounding) uint128 assetAPayment = denominateAssetBInA(amountBSold, _vars.currentPrice, !_self).toU128(); _tick.availableB -= amountBSold.toU120(); _tick.bToASubTick.sold += amountBSold; _tick.bToASubTick.bought += assetAPayment; _vars.offerAInB -= amountBSold; _vars.protocolSoldB += amountBSold; _vars.protocolBoughtA += assetAPayment; } } /** * @notice Fills as much of the A offered as possible * @dev Heavily uses that internal functions are passing reference to memory structures * @param _self True if buying from "self" false otherwise. */ function _useBOffer( RebalanceValues memory _vars, Tick memory _tick, bool _self ) internal pure { if (_vars.offerBInA > 0 && _tick.availableA > 0) { // Buying Asset A using Asset B uint128 amountASold = _vars.offerBInA.toU128(); if (_vars.offerBInA > _tick.availableA) { amountASold = _tick.availableA; } // Underpays actual price if self, otherwise overpay (to not mess rounding) uint128 assetBPayment = denominateAssetAInB(amountASold, _vars.currentPrice, !_self).toU128(); _tick.availableA -= amountASold.toU120(); _tick.aToBSubTick.sold += amountASold; _tick.aToBSubTick.bought += assetBPayment; _vars.offerBInA -= amountASold; _vars.protocolSoldA += amountASold; _vars.protocolBoughtB += assetBPayment; } } /** * @notice Computes the earliest tick where we had available funds * @param _earliestTickA The ealiest tick with available A * @param _earliestTickB The ealiest tick with available B * @return The earliest tick with available assets */ function _earliestUsedTick(uint256 _earliestTickA, uint256 _earliestTickB) internal pure returns (uint256) { uint256 start; if (_earliestTickA == 0 && _earliestTickB == 0) { revert NoDeposits(); } else if (_earliestTickA * _earliestTickB == 0) { // one are zero (the both case is handled explicitly above) start = _earliestTickA > _earliestTickB ? _earliestTickA : _earliestTickB; } else { start = _earliestTickA < _earliestTickB ? _earliestTickA : _earliestTickB; } return start; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-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.7.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 * ==== * * [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://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason 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 { // 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: Apache-2.0 // Copyright 2022 Aztec pragma solidity >=0.8.4; // @dev For documentation of the functions within this interface see RollupProcessor contract interface IRollupProcessor { /*---------------------------------------- EVENTS ----------------------------------------*/ event OffchainData(uint256 indexed rollupId, uint256 chunk, uint256 totalChunks, address sender); event RollupProcessed(uint256 indexed rollupId, bytes32[] nextExpectedDefiHashes, address sender); event DefiBridgeProcessed( uint256 indexed encodedBridgeCallData, uint256 indexed nonce, uint256 totalInputValue, uint256 totalOutputValueA, uint256 totalOutputValueB, bool result, bytes errorReason ); event AsyncDefiBridgeProcessed( uint256 indexed encodedBridgeCallData, uint256 indexed nonce, uint256 totalInputValue ); event Deposit(uint256 indexed assetId, address indexed depositorAddress, uint256 depositValue); event WithdrawError(bytes errorReason); event AssetAdded(uint256 indexed assetId, address indexed assetAddress, uint256 assetGasLimit); event BridgeAdded(uint256 indexed bridgeAddressId, address indexed bridgeAddress, uint256 bridgeGasLimit); event RollupProviderUpdated(address indexed providerAddress, bool valid); event VerifierUpdated(address indexed verifierAddress); event Paused(address account); event Unpaused(address account); /*---------------------------------------- MUTATING FUNCTIONS ----------------------------------------*/ function pause() external; function unpause() external; function setRollupProvider(address _provider, bool _valid) external; function setVerifier(address _verifier) external; function setAllowThirdPartyContracts(bool _allowThirdPartyContracts) external; function setDefiBridgeProxy(address _defiBridgeProxy) external; function setSupportedAsset(address _token, uint256 _gasLimit) external; function setSupportedBridge(address _bridge, uint256 _gasLimit) external; function processRollup(bytes calldata _encodedProofData, bytes calldata _signatures) external; function receiveEthFromBridge(uint256 _interactionNonce) external payable; function approveProof(bytes32 _proofHash) external; function depositPendingFunds( uint256 _assetId, uint256 _amount, address _owner, bytes32 _proofHash ) external payable; function offchainData( uint256 _rollupId, uint256 _chunk, uint256 _totalChunks, bytes calldata _offchainTxData ) external; function processAsyncDefiInteraction(uint256 _interactionNonce) external returns (bool); /*---------------------------------------- NON-MUTATING FUNCTIONS ----------------------------------------*/ function rollupStateHash() external view returns (bytes32); function userPendingDeposits(uint256 _assetId, address _user) external view returns (uint256); function defiBridgeProxy() external view returns (address); function prevDefiInteractionsHash() external view returns (bytes32); function paused() external view returns (bool); function verifier() external view returns (address); function getDataSize() external view returns (uint256); function getPendingDefiInteractionHashesLength() external view returns (uint256); function getDefiInteractionHashesLength() external view returns (uint256); function getAsyncDefiInteractionHashesLength() external view returns (uint256); function getSupportedBridge(uint256 _bridgeAddressId) external view returns (address); function getSupportedBridgesLength() external view returns (uint256); function getSupportedAssetsLength() external view returns (uint256); function getSupportedAsset(uint256 _assetId) external view returns (address); function getEscapeHatchStatus() external view returns (bool, uint256); function assetGasLimits(uint256 _bridgeAddressId) external view returns (uint256); function bridgeGasLimits(uint256 _bridgeAddressId) external view returns (uint256); }
// SPDX-License-Identifier: Apache-2.0 // Copyright 2022 Aztec. pragma solidity >=0.8.4; import {IDefiBridge} from "../../aztec/interfaces/IDefiBridge.sol"; import {ISubsidy} from "../../aztec/interfaces/ISubsidy.sol"; import {AztecTypes} from "../../aztec/libraries/AztecTypes.sol"; import {ErrorLib} from "./ErrorLib.sol"; /** * @title BridgeBase * @notice A base that bridges can be built upon which imports a limited set of features * @dev Reverts `convert` with missing implementation, and `finalise` with async disabled * @author Lasse Herskind */ abstract contract BridgeBase is IDefiBridge { error MissingImplementation(); ISubsidy public constant SUBSIDY = ISubsidy(0xABc30E831B5Cc173A9Ed5941714A7845c909e7fA); address public immutable ROLLUP_PROCESSOR; constructor(address _rollupProcessor) { ROLLUP_PROCESSOR = _rollupProcessor; } modifier onlyRollup() { if (msg.sender != ROLLUP_PROCESSOR) { revert ErrorLib.InvalidCaller(); } _; } function convert( AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata, uint256, uint256, uint64, address ) external payable virtual override(IDefiBridge) returns ( uint256, uint256, bool ) { revert MissingImplementation(); } function finalise( AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata, uint256, uint64 ) external payable virtual override(IDefiBridge) returns ( uint256, uint256, bool ) { revert ErrorLib.AsyncDisabled(); } /** * @notice Computes the criteria that is passed on to the subsidy contract when claiming * @dev Should be overridden by bridge implementation if intended to limit subsidy. * @return The criteria to be passed along */ function computeCriteria( AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata, AztecTypes.AztecAsset calldata, uint64 ) public view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: Apache-2.0 // Copyright 2022 Aztec. pragma solidity >=0.8.4; library ErrorLib { error InvalidCaller(); error InvalidInput(); error InvalidInputA(); error InvalidInputB(); error InvalidOutputA(); error InvalidOutputB(); error InvalidInputAmount(); error InvalidAuxData(); error ApproveFailed(address token); error TransferFailed(address token); error InvalidNonce(); error AsyncDisabled(); }
// SPDX-License-Identifier: Apache-2.0 // Copyright 2022 Aztec pragma solidity >=0.8.4; library AztecTypes { enum AztecAssetType { NOT_USED, ETH, ERC20, VIRTUAL } struct AztecAsset { uint256 id; address erc20Address; AztecAssetType assetType; } }
// SPDX-License-Identifier: Apache-2.0 // Copyright 2022 Aztec. pragma solidity >=0.8.4; library SafeCastLib { function toU128(uint256 _a) internal pure returns (uint128) { if (_a > type(uint128).max) { revert("Overflow"); } return uint128(_a); } function toU120(uint256 _a) internal pure returns (uint120) { if (_a > type(uint120).max) { revert("Overflow"); } return uint120(_a); } function toU32(uint256 _a) internal pure returns (uint32) { if (_a > type(uint32).max) { revert("Overflow"); } return uint32(_a); } }
// SPDX-License-Identifier: Apache-2.0 // Copyright 2022 Aztec pragma solidity >=0.8.4; import {AztecTypes} from "../libraries/AztecTypes.sol"; interface IDefiBridge { /** * @notice A function which converts input assets to output assets. * @param _inputAssetA A struct detailing the first input asset * @param _inputAssetB A struct detailing the second input asset * @param _outputAssetA A struct detailing the first output asset * @param _outputAssetB A struct detailing the second output asset * @param _totalInputValue An amount of input assets transferred to the bridge (Note: "total" is in the name * because the value can represent summed/aggregated token amounts of users actions on L2) * @param _interactionNonce A globally unique identifier of this interaction/`convert(...)` call. * @param _auxData Bridge specific data to be passed into the bridge contract (e.g. slippage, nftID etc.) * @return outputValueA An amount of `_outputAssetA` returned from this interaction. * @return outputValueB An amount of `_outputAssetB` returned from this interaction. * @return isAsync A flag indicating if the interaction is async. * @dev This function is called from the RollupProcessor contract via the DefiBridgeProxy. Before this function is * called _RollupProcessor_ contract will have sent you all the assets defined by the input params. This * function is expected to convert input assets to output assets (e.g. on Uniswap) and return the amounts * of output assets to be received by the _RollupProcessor_. If output assets are ERC20 tokens the bridge has * to _RollupProcessor_ as a spender before the interaction is finished. If some of the output assets is ETH * it has to be sent to _RollupProcessor_ via the `receiveEthFromBridge(uint256 _interactionNonce)` method * inside before the `convert(...)` function call finishes. * @dev If there are two input assets, equal amounts of both assets will be transferred to the bridge before this * method is called. * @dev **BOTH** output assets could be virtual but since their `assetId` is currently assigned as * `_interactionNonce` it would simply mean that more of the same virtual asset is minted. * @dev If this interaction is async the function has to return `(0,0 true)`. Async interaction will be finalised at * a later time and its output assets will be returned in a `IDefiBridge.finalise(...)` call. **/ function convert( AztecTypes.AztecAsset calldata _inputAssetA, AztecTypes.AztecAsset calldata _inputAssetB, AztecTypes.AztecAsset calldata _outputAssetA, AztecTypes.AztecAsset calldata _outputAssetB, uint256 _totalInputValue, uint256 _interactionNonce, uint64 _auxData, address _rollupBeneficiary ) external payable returns ( uint256 outputValueA, uint256 outputValueB, bool isAsync ); /** * @notice A function that finalises asynchronous interaction. * @param _inputAssetA A struct detailing the first input asset * @param _inputAssetB A struct detailing the second input asset * @param _outputAssetA A struct detailing the first output asset * @param _outputAssetB A struct detailing the second output asset * @param _interactionNonce A globally unique identifier of this interaction/`convert(...)` call. * @param _auxData Bridge specific data to be passed into the bridge contract (e.g. slippage, nftID etc.) * @return outputValueA An amount of `_outputAssetA` returned from this interaction. * @return outputValueB An amount of `_outputAssetB` returned from this interaction. * @dev This function should use the `BridgeBase.onlyRollup()` modifier to ensure it can only be called from * the `RollupProcessor.processAsyncDefiInteraction(uint256 _interactionNonce)` method. **/ function finalise( AztecTypes.AztecAsset calldata _inputAssetA, AztecTypes.AztecAsset calldata _inputAssetB, AztecTypes.AztecAsset calldata _outputAssetA, AztecTypes.AztecAsset calldata _outputAssetB, uint256 _interactionNonce, uint64 _auxData ) external payable returns ( uint256 outputValueA, uint256 outputValueB, bool interactionComplete ); }
// SPDX-License-Identifier: Apache-2.0 // Copyright 2022 Aztec pragma solidity >=0.8.4; // @dev documentation of this interface is in its implementation (Subsidy contract) interface ISubsidy { /** * @notice Container for Subsidy related information * @member available Amount of ETH remaining to be paid out * @member gasUsage Amount of gas the interaction consumes (used to define max possible payout) * @member minGasPerMinute Minimum amount of gas per minute the subsidizer has to subsidize * @member gasPerMinute Amount of gas per minute the subsidizer is willing to subsidize * @member lastUpdated Last time subsidy was paid out or funded (if not subsidy was yet claimed after funding) */ struct Subsidy { uint128 available; uint32 gasUsage; uint32 minGasPerMinute; uint32 gasPerMinute; uint32 lastUpdated; } function setGasUsageAndMinGasPerMinute( uint256 _criteria, uint32 _gasUsage, uint32 _minGasPerMinute ) external; function setGasUsageAndMinGasPerMinute( uint256[] calldata _criteria, uint32[] calldata _gasUsage, uint32[] calldata _minGasPerMinute ) external; function registerBeneficiary(address _beneficiary) external; function subsidize( address _bridge, uint256 _criteria, uint32 _gasPerMinute ) external payable; function topUp(address _bridge, uint256 _criteria) external payable; function claimSubsidy(uint256 _criteria, address _beneficiary) external returns (uint256); function withdraw(address _beneficiary) external returns (uint256); // solhint-disable-next-line function MIN_SUBSIDY_VALUE() external view returns (uint256); function claimableAmount(address _beneficiary) external view returns (uint256); function isRegistered(address _beneficiary) external view returns (bool); function getSubsidy(address _bridge, uint256 _criteria) external view returns (Subsidy memory); function getAccumulatedSubsidyAmount(address _bridge, uint256 _criteria) external view returns (uint256); }
{ "remappings": [ "@openzeppelin/=node_modules/@openzeppelin/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/" ], "optimizer": { "enabled": true, "runs": 100000 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_rollupProcessor","type":"address"},{"internalType":"uint256","name":"_tickSize","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FeeTooLarge","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidInputA","type":"error"},{"inputs":[],"name":"InvalidOutputA","type":"error"},{"inputs":[],"name":"MissingImplementation","type":"error"},{"inputs":[],"name":"NegativePrice","type":"error"},{"inputs":[],"name":"NoDeposits","type":"error"},{"inputs":[],"name":"PositionAlreadyExists","type":"error"},{"inputs":[],"name":"ASSET_A","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ASSET_B","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE","outputs":[{"internalType":"contract IChainlinkOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLLUP_PROCESSOR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SLIPPAGE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBSIDY","outputs":[{"internalType":"contract ISubsidy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TICK_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNI_ROUTER","outputs":[{"internalType":"contract ISwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"computeCriteria","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"_inputAssetA","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"_outputAssetA","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"internalType":"uint256","name":"_inputValue","type":"uint256"},{"internalType":"uint256","name":"_interactionNonce","type":"uint256"},{"internalType":"uint64","name":"_numTicks","type":"uint64"},{"internalType":"address","name":"","type":"address"}],"name":"convert","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"dcas","outputs":[{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint32","name":"start","type":"uint32"},{"internalType":"uint32","name":"end","type":"uint32"},{"internalType":"bool","name":"aToB","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_priceAToB","type":"uint256"},{"internalType":"bool","name":"_roundUp","type":"bool"}],"name":"denominateAssetAInB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_priceAToB","type":"uint256"},{"internalType":"bool","name":"_roundUp","type":"bool"}],"name":"denominateAssetBInA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"earliestTickWithAvailableA","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"earliestTickWithAvailableB","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"_outputAssetA","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"enum AztecTypes.AztecAssetType","name":"assetType","type":"uint8"}],"internalType":"struct AztecTypes.AztecAsset","name":"","type":"tuple"},{"internalType":"uint256","name":"_interactionNonce","type":"uint256"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"finalise","outputs":[{"internalType":"uint256","name":"outputValueA","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"interactionComplete","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"getAccumulated","outputs":[{"internalType":"uint256","name":"accumulated","type":"uint256"},{"internalType":"bool","name":"ready","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAvailable","outputs":[{"internalType":"uint256","name":"availableA","type":"uint256"},{"internalType":"uint256","name":"availableB","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"getDCA","outputs":[{"components":[{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint32","name":"start","type":"uint32"},{"internalType":"uint32","name":"end","type":"uint32"},{"internalType":"bool","name":"aToB","type":"bool"}],"internalType":"struct BiDCABridge.DCA","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tick","type":"uint256"}],"name":"getTick","outputs":[{"components":[{"internalType":"uint120","name":"availableA","type":"uint120"},{"internalType":"uint120","name":"availableB","type":"uint120"},{"internalType":"uint16","name":"poke","type":"uint16"},{"components":[{"internalType":"uint128","name":"sold","type":"uint128"},{"internalType":"uint128","name":"bought","type":"uint128"}],"internalType":"struct BiDCABridge.SubTick","name":"aToBSubTick","type":"tuple"},{"components":[{"internalType":"uint128","name":"sold","type":"uint128"},{"internalType":"uint128","name":"bought","type":"uint128"}],"internalType":"struct BiDCABridge.SubTick","name":"bToASubTick","type":"tuple"},{"internalType":"uint128","name":"priceOfAInB","type":"uint128"},{"internalType":"uint32","name":"priceTime","type":"uint32"}],"internalType":"struct BiDCABridge.Tick","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_numTicks","type":"uint256"}],"name":"pokeNextTicks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_startTick","type":"uint256"},{"internalType":"uint256","name":"_numTicks","type":"uint256"}],"name":"pokeTicks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_offerA","type":"uint256"},{"internalType":"uint256","name":"_offerB","type":"uint256"},{"internalType":"uint256","name":"_upperTick","type":"uint256"}],"name":"rebalanceAndFill","outputs":[{"internalType":"int256","name":"","type":"int256"},{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_offerA","type":"uint256"},{"internalType":"uint256","name":"_offerB","type":"uint256"}],"name":"rebalanceAndFill","outputs":[{"internalType":"int256","name":"","type":"int256"},{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_upperTick","type":"uint256"}],"name":"rebalanceAndFillUniswap","outputs":[{"internalType":"int256","name":"","type":"int256"},{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rebalanceAndFillUniswap","outputs":[{"internalType":"int256","name":"","type":"int256"},{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ticks","outputs":[{"internalType":"uint120","name":"availableA","type":"uint120"},{"internalType":"uint120","name":"availableB","type":"uint120"},{"internalType":"uint16","name":"poke","type":"uint16"},{"components":[{"internalType":"uint128","name":"sold","type":"uint128"},{"internalType":"uint128","name":"bought","type":"uint128"}],"internalType":"struct BiDCABridge.SubTick","name":"aToBSubTick","type":"tuple"},{"components":[{"internalType":"uint128","name":"sold","type":"uint128"},{"internalType":"uint128","name":"bought","type":"uint128"}],"internalType":"struct BiDCABridge.SubTick","name":"bToASubTick","type":"tuple"},{"internalType":"uint128","name":"priceOfAInB","type":"uint128"},{"internalType":"uint32","name":"priceTime","type":"uint32"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101206040523480156200001257600080fd5b50604051620049fe380380620049fe833981016040819052620000359162000546565b6001600160a01b038316608052736b175474e89094c44da98b954eedeac495271d0f60a081905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260c081905260e084905284919084846200009b848660001962000180602090811b62001e2c17901c565b620000c285600019856001600160a01b03166200018060201b62001e2c179092919060201c565b612710811115620000e657604051637e2df70960e11b815260040160405180910390fd5b6101005250620001349250736b175474e89094c44da98b954eedeac495271d0f915073e592427a0aece92de3edee1f18e0157c05861564905060001962000180602090811b62001e2c17901c565b6200017773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273e592427a0aece92de3edee1f18e0157c0586156460001962000180602090811b62001e2c17901c565b5050506200064f565b801580620001fe5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015620001d6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001fc91906200058b565b155b620002765760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620002ce918591620002d316565b505050565b60006200032f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620003b160201b62002031179092919060201c565b805190915015620002ce5780806020019051810190620003509190620005a5565b620002ce5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016200026d565b6060620003c28484600085620003cc565b90505b9392505050565b6060824710156200042f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016200026d565b6001600160a01b0385163b620004885760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016200026d565b600080866001600160a01b03168587604051620004a69190620005fc565b60006040518083038185875af1925050503d8060008114620004e5576040519150601f19603f3d011682016040523d82523d6000602084013e620004ea565b606091505b509092509050620004fd82828662000508565b979650505050505050565b6060831562000519575081620003c5565b8251156200052a5782518084602001fd5b8160405162461bcd60e51b81526004016200026d91906200061a565b6000806000606084860312156200055c57600080fd5b83516001600160a01b03811681146200057457600080fd5b602085015160409095015190969495509392505050565b6000602082840312156200059e57600080fd5b5051919050565b600060208284031215620005b857600080fd5b81518015158114620003c557600080fd5b60005b83811015620005e6578181015183820152602001620005cc565b83811115620005f6576000848401525b50505050565b6000825162000610818460208701620005c9565b9190910192915050565b60208152600082518060208401526200063b816040850160208701620005c9565b601f01601f19169190910160400192915050565b60805160a05160c05160e051610100516142c26200073c600039600081816107050152818161147601526114a201526000818161067001528181611d7701528181612be10152818161317801526131a60152600081816108c701528181610b0b01528181610c110152818161104c015281816110a6015281816113ee015281816117d6015261196801526000818161063c01528181610ab401528181610b9501528181610beb01528181610fa801528181611002015281816113c80152818161173a0152611a040152600081816106a40152818161093a015281816112cf01526115c501526142c26000f3fe6080604052600436106101d15760003560e01c80639e0e5555116100f7578063c57981b511610095578063ee0ab46511610064578063ee0ab4651461088d578063f577279b146108b5578063f8f7e258146108e9578063f9cc06051461090957600080fd5b8063c57981b5146106f3578063c91e083614610727578063dbeacd541461073c578063ed2b85481461076257600080fd5b8063a24f6d91116100d1578063a24f6d911461062a578063abc11cd01461065e578063ae9467b514610692578063be2505ae146106c657600080fd5b80639e0e5555146105d45780639e93ad8e146105f4578063a24b87461461060a57600080fd5b8063422a787f1161016f5780638f88553b1161013e5780638f88553b146104b4578063901f4cd01461058c57806398d5fdca146105ac5780639b07d342146105c157600080fd5b8063422a787f14610343578063534cb30d146103635780636508156e1461046a5780637c26f0641461049257600080fd5b806338013f02116101ab57806338013f02146102675780633a55355b146102b45780633aa0f6d3146102e95780633be44da21461031e57600080fd5b806326c3b515146101dd57806336b4134a14610212578063374a0d961461023557600080fd5b366101d857005b600080fd5b6101f06101eb3660046138a8565b61091e565b6040805193845260208401929092521515908201526060015b60405180910390f35b34801561021e57600080fd5b50610227606481565b604051908152602001610209565b34801561024157600080fd5b506000546102529063ffffffff1681565b60405163ffffffff9091168152602001610209565b34801561027357600080fd5b5061028f73773616e4d11a78f511299002da57a0a94577f1f481565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610209565b3480156102c057600080fd5b506102d46102cf36600461393a565b610d24565b60408051928352901515602083015201610209565b3480156102f557600080fd5b50610309610304366004613953565b610f64565b60408051928352602083019190915201610209565b34801561032a57600080fd5b5060005461025290640100000000900463ffffffff1681565b34801561034f57600080fd5b5061022761035e36600461398d565b6110d9565b34801561036f57600080fd5b5061045761037e36600461393a565b600160208181526000928352604092839020805484518086018652938201546fffffffffffffffffffffffffffffffff8082168652700100000000000000000000000000000000918290048116868601528651808801909752600284015480821688528290048116948701949094526003909201546effffffffffffffffffffffffffffff808316966f010000000000000000000000000000008404909116957e0100000000000000000000000000000000000000000000000000000000000090930461ffff1694929390928216910463ffffffff1687565b60405161020997969594939291906139c6565b34801561047657600080fd5b5061028f73abc30e831b5cc173a9ed5941714a7845c909e7fa81565b34801561049e57600080fd5b506104b26104ad366004613a74565b61114a565b005b3480156104c057600080fd5b5061054d6104cf36600461393a565b6002602052600090815260409020546fffffffffffffffffffffffffffffffff81169063ffffffff70010000000000000000000000000000000082048116917401000000000000000000000000000000000000000081049091169060ff78010000000000000000000000000000000000000000000000009091041684565b604080516fffffffffffffffffffffffffffffffff95909516855263ffffffff9384166020860152919092169083015215156060820152608001610209565b34801561059857600080fd5b506104b26105a736600461393a565b6111d2565b3480156105b857600080fd5b506102276111e7565b6101f06105cf366004613a96565b6112b3565b3480156105e057600080fd5b506103096105ef366004613a74565b611673565b34801561060057600080fd5b5061022761271081565b34801561061657600080fd5b5061030961062536600461393a565b6116ac565b34801561063657600080fd5b5061028f7f000000000000000000000000000000000000000000000000000000000000000081565b34801561066a57600080fd5b506102277f000000000000000000000000000000000000000000000000000000000000000081565b34801561069e57600080fd5b5061028f7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106d257600080fd5b506106e66106e136600461393a565b611b86565b6040516102099190613b0b565b3480156106ff57600080fd5b506102277f000000000000000000000000000000000000000000000000000000000000000081565b34801561073357600080fd5b50610309611cde565b34801561074857600080fd5b50610227610757366004613bd5565b600095945050505050565b34801561076e57600080fd5b5061083b61077d36600461393a565b60408051608080820183526000808352602080840182905283850182905260609384018290529481526002855283902083519182018452546fffffffffffffffffffffffffffffffff81168252700100000000000000000000000000000000810463ffffffff9081169583019590955274010000000000000000000000000000000000000000810490941692810192909252780100000000000000000000000000000000000000000000000090920460ff1615159181019190915290565b6040805182516fffffffffffffffffffffffffffffffff16815260208084015163ffffffff90811691830191909152838301511691810191909152606091820151151591810191909152608001610209565b34801561089957600080fd5b5061028f73e592427a0aece92de3edee1f18e0157c0586156481565b3480156108c157600080fd5b5061028f7f000000000000000000000000000000000000000000000000000000000000000081565b3480156108f557600080fd5b5061022761090436600461398d565b611d10565b34801561091557600080fd5b50610309611d4b565b600080803373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610991576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109a360408d0160208e01613c41565b905060006109b760408c0160208d01613c41565b905060018d60400160208101906109ce9190613c8b565b60038111156109df576109df613c5c565b1415610a725773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff1663d0e30db08a6040518263ffffffff1660e01b81526004016000604051808303818588803b158015610a4157600080fd5b505af1158015610a55573d6000803e3d6000fd5b505050505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc291505b6001610a8460608d0160408e01613c8b565b6003811115610a9557610a95613c5c565b1415610ab2575073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015610b5a57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15610b91576040517fc582880b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614905080610c0f577f0000000000000000000000000000000000000000000000000000000000000000610c31565b7f00000000000000000000000000000000000000000000000000000000000000005b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614610c95576040517f6c98dcaf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600089815260026020526040902054700100000000000000000000000000000000900463ffffffff1615610cf5576040517f6e8de45800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d0b898b8a67ffffffffffffffff1684612040565b5060009d8e9d5060019c509a5050505050505050505050565b6000818152600260209081526040808320815160808101835290546fffffffffffffffffffffffffffffffff8116825263ffffffff700100000000000000000000000000000000820481169483018590527401000000000000000000000000000000000000000082041692820183905260ff780100000000000000000000000000000000000000000000000090910416151560608201528392909183610dca8383613cdb565b8451610de891906fffffffffffffffffffffffffffffffff16613d21565b606085015160019650909150835b83811015610f5957600081815260016020526040812090808085610e7057835460028501546f010000000000000000000000000000009091046effffffffffffffffffffffffffffff16906fffffffffffffffffffffffffffffffff80821691700100000000000000000000000000000000900416610eb6565b835460018501546effffffffffffffffffffffffffffff909116906fffffffffffffffffffffffffffffffff808216917001000000000000000000000000000000009004165b6fffffffffffffffffffffffffffffffff1692506fffffffffffffffffffffffffffffffff1692506effffffffffffffffffffffffffffff1692508a8015610efc575082155b8015610f085750600082115b9a508115610f3357610f1a8383613d35565b610f248883613d4d565b610f2e9190613d21565b610f36565b60005b610f40908d613d35565b9b50505050508080610f5190613d8a565b915050610df6565b505050505050915091565b600080600080610f7f8787610f776111e7565b886000612432565b5050915091506000821315610fd557610fd073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333085612b23565b611029565b60008212156110295761102933610feb84613dc3565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190612b87565b60008113156110795761107473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084612b23565b6110cd565b60008112156110cd576110cd3361108f83613dc3565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190612b87565b90969095509350505050565b6000811561112357670de0b6b3a764000060016110f68587613d4d565b61110890670de0b6b3a7640000613d35565b6111129190613cdb565b61111c9190613d21565b9050611143565b670de0b6b3a76400006111368486613d4d565b6111409190613d21565b90505b9392505050565b815b6111568284613d35565b8110156111cd57600081815260016020526040902080547e01000000000000000000000000000000000000000000000000000000000000900461ffff1690601e61119f83613dfc565b91906101000a81548161ffff021916908361ffff1602179055505080806111c590613d8a565b91505061114c565b505050565b6111e46111de42612bdd565b8261114a565b50565b60008073773616e4d11a78f511299002da57a0a94577f1f473ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015611249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126d9190613e38565b50505091505060008112156112ae576040517f61ca76d200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b600080803373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611326576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061133186610d24565b9250905081156116665760008061134e60408b0160208c01613c41565b9050600161136260608c0160408d01613c8b565b600381111561137357611373613c5c565b141561139457506001905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25b6000888152600260205260409020547801000000000000000000000000000000000000000000000000900460ff166113ec577f000000000000000000000000000000000000000000000000000000000000000061140e565b7f00000000000000000000000000000000000000000000000000000000000000005b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611472576040517f6c98dcaf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f0000000000000000000000000000000000000000000000000000000000000000156114d4576127106114c77f000000000000000000000000000000000000000000000000000000000000000086613d4d565b6114d19190613d21565b90505b6114de8185613cdb565b60008a815260026020526040902080547fffffffffffffff000000000000000000000000000000000000000000000000001690559650821561163b576040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810188905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d90602401600060405180830381600087803b15801561158057600080fd5b505af1158015611594573d6000803e3d6000fd5b50506040517f12a53623000000000000000000000000000000000000000000000000000000008152600481018c90527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1692506312a53623915089906024016000604051808303818588803b15801561162157600080fd5b505af1158015611635573d6000803e3d6000fd5b50505050505b80156116625761166273ffffffffffffffffffffffffffffffffffffffff83163283612b87565b5050505b5096509650969350505050565b6000806116a184847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610f64565b915091509250929050565b60008060006116b96111e7565b90506000806000806116d0600080878b6001612432565b93509350935093506000821180156116e85750600081115b15611706576116fb8282878b6001612432565b929650909450925090505b8115611934576040805160a081019091527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000606090811b821660c08401527d64000000000000000000000000000000000000000000000000000000000060d48401527fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000060d78401527e01f4000000000000000000000000000000000000000000000000000000000060eb8401527f0000000000000000000000000000000000000000000000000000000000000000901b1660ee82015260009073e592427a0aece92de3edee1f18e0157c058615649063c04b8d5990806101028101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152908252306020830152429082015260608101879052608001612710611876606482613cdb565b611882898d60006110d9565b61188c9190613d4d565b6118969190613d21565b8152506040518263ffffffff1660e01b81526004016118b59190613ef2565b6020604051808303816000875af11580156118d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f89190613f58565b905060008361190f83670de0b6b3a7640000613d4d565b6119199190613d21565b905061192a600083838d6001612432565b5091975095505050505b8015611b79576040805160a081019091527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000606090811b821660c08401527e01f4000000000000000000000000000000000000000000000000000000000060d48401527fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000060d78401527d64000000000000000000000000000000000000000000000000000000000060eb8401527f0000000000000000000000000000000000000000000000000000000000000000901b1660ee82015260009073e592427a0aece92de3edee1f18e0157c058615649063c04b8d5990806101028101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152908252306020830152429082015260608101869052608001612710611aa4606482613cdb565b611ab0888d6000611d10565b611aba9190613d4d565b611ac49190613d21565b8152506040518263ffffffff1660e01b8152600401611ae39190613ef2565b6020604051808303816000875af1158015611b02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b269190613f58565b9050600081600181611b4086670de0b6b3a7640000613d4d565b611b4a9190613d35565b611b549190613cdb565b611b5e9190613d21565b9050611b6f826000838d6001612432565b5091975095505050505b5091969095509350505050565b611be36040805160e081018252600080825260208083018290528284018290528351808501855282815280820183905260608401528351808501909452818452830152906080820190815260006020820181905260409091015290565b50600090815260016020818152604092839020835160e08101855281546effffffffffffffffffffffffffffff80821683526f01000000000000000000000000000000820416828501527e01000000000000000000000000000000000000000000000000000000000000900461ffff168186015284518086018652938201546fffffffffffffffffffffffffffffffff808216865270010000000000000000000000000000000091829004811686860152606083019590955285518087019096526002830154808616875281900485169386019390935260808101949094526003015491821660a0840152900463ffffffff1660c082015290565b600080611d0a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6116ac565b50509091565b60008115611d385782600181611d2e87670de0b6b3a7640000613d4d565b6111089190613d35565b8261113685670de0b6b3a7640000613d4d565b6000805481908190611d6e9063ffffffff80821691640100000000900416612c26565b90506000611d9c7f000000000000000000000000000000000000000000000000000000000000000042613d21565b9050815b818111611e2557600081815260016020526040902054611dd1906effffffffffffffffffffffffffffff1686613d35565b600082815260016020526040902054909550611e11906f0100000000000000000000000000000090046effffffffffffffffffffffffffffff1685613d35565b935080611e1d81613d8a565b915050611da0565b5050509091565b801580611ecc57506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eca9190613f58565b155b611f5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526111cd9084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612ca3565b60606111408484600085612daf565b600061204b42612bdd565b9050818015612060575060005463ffffffff16155b156120a45761206e81612f45565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff929092169190911790555b811580156120c05750600054640100000000900463ffffffff16155b156120ef576120ce81612f45565b600060046101000a81548163ffffffff021916908363ffffffff1602179055505b6120ff6120fa6111e7565b612fb9565b6001600061210d8285613cdb565b815260200190815260200160002060030160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555061215d42612f45565b6001600061216b8285613cdb565b815260200190815260200160002060030160106101000a81548163ffffffff021916908363ffffffff160217905550600083856121a89190613d21565b9050815b6121b68584613d35565b8110156122c6578315612234576121cc82613035565b600082815260016020526040812080549091906121fb9084906effffffffffffffffffffffffffffff16613f71565b92506101000a8154816effffffffffffffffffffffffffffff02191690836effffffffffffffffffffffffffffff1602179055506122b4565b61223d82613035565b60008281526001602052604090208054600f9061227f9084906f0100000000000000000000000000000090046effffffffffffffffffffffffffffff16613f71565b92506101000a8154816effffffffffffffffffffffffffffff02191690836effffffffffffffffffffffffffffff1602179055505b806122be81613d8a565b9150506121ac565b5060405180608001604052806122db87612fb9565b6fffffffffffffffffffffffffffffffff1681526020016122fb84612f45565b63ffffffff1681526020016123186123138786613d35565b612f45565b63ffffffff908116825294151560209182015260009788526002815260409788902082518154928401519984015160609094015115157801000000000000000000000000000000000000000000000000027fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff9488167401000000000000000000000000000000000000000002949094167fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff9a909716700100000000000000000000000000000000027fffffffffffffffffffffffff00000000000000000000000000000000000000009093166fffffffffffffffffffffffffffffffff909116179190911797909716939093179290921790945550505050565b6000806000806124a3604051806101a00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b8781526000805463ffffffff8082166020850181905264010000000090920416604084018190526124d49190612c26565b60008181526001602081815260408320600301546fffffffffffffffffffffffffffffffff8116610120880190815293859052919052700100000000000000000000000000000000900463ffffffff16610140850152519091506125a557805b6101208301516125a3578061254881613fa4565b60008181526001602081815260408320600301546fffffffffffffffffffffffffffffffff81166101208a01529284905252700100000000000000000000000000000000900463ffffffff1661014086015291506125349050565b505b6125b58b836000015160006110d9565b606083015281516125c9908b906000611d10565b608083015260006125d942612bdd565b90506125e88360000151612fb9565b600160006125f68285613cdb565b815260200190815260200160002060030160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555061264642612f45565b600160006126548285613cdb565b81526020810191909152604001600020600301805463ffffffff92909216700100000000000000000000000000000000027fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff909216919091179055815b6126bb828b6130b0565b811015612a2a57600081815260016020818152604092839020835160e08101855281546effffffffffffffffffffffffffffff80821683526f01000000000000000000000000000000820416828501527e01000000000000000000000000000000000000000000000000000000000000900461ffff168186015284518086018652938201546fffffffffffffffffffffffffffffffff808216865270010000000000000000000000000000000091829004811686860152606083019590955285518087019096526002830154808616875281900485169386019390935260808101949094526003015491821660a0840152900463ffffffff1660c08201526127c48582846130c5565b6127cf85828c6134bf565b6127da85828c61366c565b80516effffffffffffffffffffffffffffff161580156127fd5750818560200151145b15612819576001856020018181516128159190613d35565b9052505b60208101516effffffffffffffffffffffffffffff1615801561283f5750818560400151145b1561285b576001856040018181516128579190613d35565b9052505b80600001516effffffffffffffffffffffffffffff1685610160018181516128839190613d35565b9052506020810151610180860180516effffffffffffffffffffffffffffff909216916128b1908390613d35565b90525060008281526001602081815260409283902084518154838701519587015161ffff167e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6effffffffffffffffffffffffffffff9788166f01000000000000000000000000000000027fffff0000000000000000000000000000000000000000000000000000000000009093169790931696909617171693909317835560608401518051908201516fffffffffffffffffffffffffffffffff9081167001000000000000000000000000000000009081029282169290921793850193909355608085015180519201518316810291831691909117600284015560a08401516003909301805460c09095015163ffffffff169091027fffffffffffffffffffffffff0000000000000000000000000000000000000000909416929091169190911791909117905580612a2281613d8a565b9150506126b1565b50600054602084015163ffffffff9091161015612a8457612a4e8360200151612f45565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff929092169190911790555b600054604084015164010000000090910463ffffffff161015612acf57612aae8360400151612f45565b600060046101000a81548163ffffffff021916908363ffffffff1602179055505b60008360a001518460e00151612ae59190613fd9565b905060008460c00151856101000151612afe9190613fd9565b61016086015161018090960151929f909e50949c50909a509298505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052612b819085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611faf565b50505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526111cd9084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611faf565b60007f00000000000000000000000000000000000000000000000000000000000000006001612c0c8285613d35565b612c169190613cdb565b612c209190613d21565b92915050565b60008083158015612c35575082155b15612c6c576040517f1562001c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612c768385613d4d565b612c8e57828411612c87578261111c565b5082611143565b828410612c9b5782611140565b509192915050565b6000612d05826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120319092919063ffffffff16565b8051909150156111cd5780806020019051810190612d23919061404d565b6111cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611f54565b606082471015612e41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611f54565b73ffffffffffffffffffffffffffffffffffffffff85163b612ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611f54565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612ee8919061406a565b60006040518083038185875af1925050503d8060008114612f25576040519150601f19603f3d011682016040523d82523d6000602084013e612f2a565b606091505b5091509150612f3a828286613807565b979650505050505050565b600063ffffffff821115612fb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f4f766572666c6f770000000000000000000000000000000000000000000000006044820152606401611f54565b5090565b60006fffffffffffffffffffffffffffffffff821115612fb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f4f766572666c6f770000000000000000000000000000000000000000000000006044820152606401611f54565b60006effffffffffffffffffffffffffffff821115612fb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f4f766572666c6f770000000000000000000000000000000000000000000000006044820152606401611f54565b60008183116130bf5782611143565b50919050565b81516effffffffffffffffffffffffffffff16158015906130fb5750600082602001516effffffffffffffffffffffffffffff16115b156111cd5760a08201516fffffffffffffffffffffffffffffffff16801561313b57610120840181905260c083015163ffffffff16610140850152613218565b60008461014001514261314e9190613cdb565b61012086015186516131609190613fd9565b61316a9190614086565b9050600085610140015160027f00000000000000000000000000000000000000000000000000000000000000006131a19190613d21565b6131cb7f000000000000000000000000000000000000000000000000000000000000000087613d4d565b6131d59190613d35565b6131df9190613cdb565b905060006131ed82846140ee565b8761012001516131fd91906141aa565b9050600081136132105760009350613214565b8093505b5050505b600061323e6120fa85600001516effffffffffffffffffffffffffffff168460006110d9565b905083602001516effffffffffffffffffffffffffffff16816fffffffffffffffffffffffffffffffff1611156133ac5760006132956120fa86602001516effffffffffffffffffffffffffffff16856000611d10565b905084602001516effffffffffffffffffffffffffffff1685606001516020018181516132c2919061421e565b6fffffffffffffffffffffffffffffffff16905250606085015180518291906132ec90839061421e565b6fffffffffffffffffffffffffffffffff169052506080850151602001805182919061331990839061421e565b6fffffffffffffffffffffffffffffffff169052506020850151608086015180516effffffffffffffffffffffffffffff9092169161335990839061421e565b6fffffffffffffffffffffffffffffffff90811690915261337c91508216613035565b8551869061338b908390614249565b6effffffffffffffffffffffffffffff1690525050600060208501526134b8565b83600001516effffffffffffffffffffffffffffff1684608001516020018181516133d7919061421e565b6fffffffffffffffffffffffffffffffff169052506080840151805182919061340190839061421e565b6fffffffffffffffffffffffffffffffff169052506060840151602001805182919061342e90839061421e565b6fffffffffffffffffffffffffffffffff169052508351606085015180516effffffffffffffffffffffffffffff9092169161346b90839061421e565b6fffffffffffffffffffffffffffffffff9081169091526000865261349291508216613035565b846020018181516134a39190614249565b6effffffffffffffffffffffffffffff169052505b5050505050565b600083606001511180156134e85750600082602001516effffffffffffffffffffffffffffff16115b156111cd5760006134fc8460600151612fb9565b905082602001516effffffffffffffffffffffffffffff1684606001511115613537575060208201516effffffffffffffffffffffffffffff165b600061355e6120fa836fffffffffffffffffffffffffffffffff1687600001518615611d10565b905061357b826fffffffffffffffffffffffffffffffff16613035565b8460200181815161358c9190614249565b6effffffffffffffffffffffffffffff16905250608084015180518391906135b590839061421e565b6fffffffffffffffffffffffffffffffff16905250608084015160200180518291906135e290839061421e565b6fffffffffffffffffffffffffffffffff908116909152606087018051918516925090613610908390613cdb565b90525060c0850180516fffffffffffffffffffffffffffffffff84169190613639908390613d35565b90525060e0850180516fffffffffffffffffffffffffffffffff83169190613662908390613d35565b9052505050505050565b60008360800151118015613691575081516effffffffffffffffffffffffffffff1615155b156111cd5760006136a58460800151612fb9565b905082600001516effffffffffffffffffffffffffffff16846080015111156136dd575081516effffffffffffffffffffffffffffff165b60006137046120fa836fffffffffffffffffffffffffffffffff16876000015186156110d9565b9050613721826fffffffffffffffffffffffffffffffff16613035565b84518590613730908390614249565b6effffffffffffffffffffffffffffff169052506060840151805183919061375990839061421e565b6fffffffffffffffffffffffffffffffff169052506060840151602001805182919061378690839061421e565b6fffffffffffffffffffffffffffffffff9081169091526080870180519185169250906137b4908390613cdb565b90525060a0850180516fffffffffffffffffffffffffffffffff841691906137dd908390613d35565b905250610100850180516fffffffffffffffffffffffffffffffff83169190613662908390613d35565b60608315613816575081611143565b8251156138265782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f549190614279565b6000606082840312156130bf57600080fd5b803567ffffffffffffffff811681146112ae57600080fd5b803573ffffffffffffffffffffffffffffffffffffffff811681146112ae57600080fd5b600080600080600080600080610200898b0312156138c557600080fd5b6138cf8a8a61385a565b97506138de8a60608b0161385a565b96506138ed8a60c08b0161385a565b95506138fd8a6101208b0161385a565b945061018089013593506101a0890135925061391c6101c08a0161386c565b915061392b6101e08a01613884565b90509295985092959890939650565b60006020828403121561394c57600080fd5b5035919050565b60008060006060848603121561396857600080fd5b505081359360208301359350604090920135919050565b80151581146111e457600080fd5b6000806000606084860312156139a257600080fd5b833592506020840135915060408401356139bb8161397f565b809150509250925092565b6effffffffffffffffffffffffffffff88811682528716602082015261ffff861660408201526101208101613a1d606083018780516fffffffffffffffffffffffffffffffff908116835260209182015116910152565b84516fffffffffffffffffffffffffffffffff90811660a084015260208601511660c08301526fffffffffffffffffffffffffffffffff841660e083015263ffffffff831661010083015298975050505050505050565b60008060408385031215613a8757600080fd5b50508035926020909101359150565b6000806000806000806101c08789031215613ab057600080fd5b613aba888861385a565b9550613ac9886060890161385a565b9450613ad88860c0890161385a565b9350613ae888610120890161385a565b92506101808701359150613aff6101a0880161386c565b90509295509295509295565b6000610120820190506effffffffffffffffffffffffffffff8084511683528060208501511660208401525061ffff60408401511660408301526060830151613b76606084018280516fffffffffffffffffffffffffffffffff908116835260209182015116910152565b50608083015180516fffffffffffffffffffffffffffffffff90811660a085015260208201511660c08401525060a08301516fffffffffffffffffffffffffffffffff1660e083015260c09092015163ffffffff166101009091015290565b60008060008060006101a08688031215613bee57600080fd5b613bf8878761385a565b9450613c07876060880161385a565b9350613c168760c0880161385a565b9250613c2687610120880161385a565b9150613c35610180870161386c565b90509295509295909350565b600060208284031215613c5357600080fd5b61114382613884565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215613c9d57600080fd5b81356004811061114357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613ced57613ced613cac565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613d3057613d30613cf2565b500490565b60008219821115613d4857613d48613cac565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613d8557613d85613cac565b500290565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613dbc57613dbc613cac565b5060010190565b60007f8000000000000000000000000000000000000000000000000000000000000000821415613df557613df5613cac565b5060000390565b600061ffff80831681811415613e1457613e14613cac565b6001019392505050565b805169ffffffffffffffffffff811681146112ae57600080fd5b600080600080600060a08688031215613e5057600080fd5b613e5986613e1e565b9450602086015193506040860151925060608601519150613c3560808701613e1e565b60005b83811015613e97578181015183820152602001613e7f565b83811115612b815750506000910152565b60008151808452613ec0816020860160208601613e7c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000825160a06020840152613f0e60c0840182613ea8565b905073ffffffffffffffffffffffffffffffffffffffff60208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b600060208284031215613f6a57600080fd5b5051919050565b60006effffffffffffffffffffffffffffff808316818516808303821115613f9b57613f9b613cac565b01949350505050565b600081613fb357613fb3613cac565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561401357614013613cac565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561404757614047613cac565b50500390565b60006020828403121561405f57600080fd5b81516111438161397f565b6000825161407c818460208701613e7c565b9190910192915050565b60008261409557614095613cf2565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156140e9576140e9613cac565b500590565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561412f5761412f613cac565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561416a5761416a613cac565b6000871292508782058712848416161561418657614186613cac565b8785058712818416161561419c5761419c613cac565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156141e4576141e4613cac565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561421857614218613cac565b50500190565b60006fffffffffffffffffffffffffffffffff808316818516808303821115613f9b57613f9b613cac565b60006effffffffffffffffffffffffffffff8381169083168181101561427157614271613cac565b039392505050565b6020815260006111436020830184613ea856fea2646970667358221220dadb774879862d74b0e99a5df4951bbca87781aba24dabf096b57c8b2786c66a64736f6c634300080a0033000000000000000000000000ff1f2b4adb9df6fc8eafecdcbf96a2b3516804550000000000000000000000000000000000000000000000000000000000015180000000000000000000000000000000000000000000000000000000000000000a
Deployed Bytecode
0x6080604052600436106101d15760003560e01c80639e0e5555116100f7578063c57981b511610095578063ee0ab46511610064578063ee0ab4651461088d578063f577279b146108b5578063f8f7e258146108e9578063f9cc06051461090957600080fd5b8063c57981b5146106f3578063c91e083614610727578063dbeacd541461073c578063ed2b85481461076257600080fd5b8063a24f6d91116100d1578063a24f6d911461062a578063abc11cd01461065e578063ae9467b514610692578063be2505ae146106c657600080fd5b80639e0e5555146105d45780639e93ad8e146105f4578063a24b87461461060a57600080fd5b8063422a787f1161016f5780638f88553b1161013e5780638f88553b146104b4578063901f4cd01461058c57806398d5fdca146105ac5780639b07d342146105c157600080fd5b8063422a787f14610343578063534cb30d146103635780636508156e1461046a5780637c26f0641461049257600080fd5b806338013f02116101ab57806338013f02146102675780633a55355b146102b45780633aa0f6d3146102e95780633be44da21461031e57600080fd5b806326c3b515146101dd57806336b4134a14610212578063374a0d961461023557600080fd5b366101d857005b600080fd5b6101f06101eb3660046138a8565b61091e565b6040805193845260208401929092521515908201526060015b60405180910390f35b34801561021e57600080fd5b50610227606481565b604051908152602001610209565b34801561024157600080fd5b506000546102529063ffffffff1681565b60405163ffffffff9091168152602001610209565b34801561027357600080fd5b5061028f73773616e4d11a78f511299002da57a0a94577f1f481565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610209565b3480156102c057600080fd5b506102d46102cf36600461393a565b610d24565b60408051928352901515602083015201610209565b3480156102f557600080fd5b50610309610304366004613953565b610f64565b60408051928352602083019190915201610209565b34801561032a57600080fd5b5060005461025290640100000000900463ffffffff1681565b34801561034f57600080fd5b5061022761035e36600461398d565b6110d9565b34801561036f57600080fd5b5061045761037e36600461393a565b600160208181526000928352604092839020805484518086018652938201546fffffffffffffffffffffffffffffffff8082168652700100000000000000000000000000000000918290048116868601528651808801909752600284015480821688528290048116948701949094526003909201546effffffffffffffffffffffffffffff808316966f010000000000000000000000000000008404909116957e0100000000000000000000000000000000000000000000000000000000000090930461ffff1694929390928216910463ffffffff1687565b60405161020997969594939291906139c6565b34801561047657600080fd5b5061028f73abc30e831b5cc173a9ed5941714a7845c909e7fa81565b34801561049e57600080fd5b506104b26104ad366004613a74565b61114a565b005b3480156104c057600080fd5b5061054d6104cf36600461393a565b6002602052600090815260409020546fffffffffffffffffffffffffffffffff81169063ffffffff70010000000000000000000000000000000082048116917401000000000000000000000000000000000000000081049091169060ff78010000000000000000000000000000000000000000000000009091041684565b604080516fffffffffffffffffffffffffffffffff95909516855263ffffffff9384166020860152919092169083015215156060820152608001610209565b34801561059857600080fd5b506104b26105a736600461393a565b6111d2565b3480156105b857600080fd5b506102276111e7565b6101f06105cf366004613a96565b6112b3565b3480156105e057600080fd5b506103096105ef366004613a74565b611673565b34801561060057600080fd5b5061022761271081565b34801561061657600080fd5b5061030961062536600461393a565b6116ac565b34801561063657600080fd5b5061028f7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f81565b34801561066a57600080fd5b506102277f000000000000000000000000000000000000000000000000000000000001518081565b34801561069e57600080fd5b5061028f7f000000000000000000000000ff1f2b4adb9df6fc8eafecdcbf96a2b35168045581565b3480156106d257600080fd5b506106e66106e136600461393a565b611b86565b6040516102099190613b0b565b3480156106ff57600080fd5b506102277f000000000000000000000000000000000000000000000000000000000000000a81565b34801561073357600080fd5b50610309611cde565b34801561074857600080fd5b50610227610757366004613bd5565b600095945050505050565b34801561076e57600080fd5b5061083b61077d36600461393a565b60408051608080820183526000808352602080840182905283850182905260609384018290529481526002855283902083519182018452546fffffffffffffffffffffffffffffffff81168252700100000000000000000000000000000000810463ffffffff9081169583019590955274010000000000000000000000000000000000000000810490941692810192909252780100000000000000000000000000000000000000000000000090920460ff1615159181019190915290565b6040805182516fffffffffffffffffffffffffffffffff16815260208084015163ffffffff90811691830191909152838301511691810191909152606091820151151591810191909152608001610209565b34801561089957600080fd5b5061028f73e592427a0aece92de3edee1f18e0157c0586156481565b3480156108c157600080fd5b5061028f7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b3480156108f557600080fd5b5061022761090436600461398d565b611d10565b34801561091557600080fd5b50610309611d4b565b600080803373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ff1f2b4adb9df6fc8eafecdcbf96a2b3516804551614610991576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109a360408d0160208e01613c41565b905060006109b760408c0160208d01613c41565b905060018d60400160208101906109ce9190613c8b565b60038111156109df576109df613c5c565b1415610a725773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff1663d0e30db08a6040518263ffffffff1660e01b81526004016000604051808303818588803b158015610a4157600080fd5b505af1158015610a55573d6000803e3d6000fd5b505050505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc291505b6001610a8460608d0160408e01613c8b565b6003811115610a9557610a95613c5c565b1415610ab2575073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25b7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015610b5a57507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15610b91576040517fc582880b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614905080610c0f577f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f610c31565b7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614610c95576040517f6c98dcaf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600089815260026020526040902054700100000000000000000000000000000000900463ffffffff1615610cf5576040517f6e8de45800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d0b898b8a67ffffffffffffffff1684612040565b5060009d8e9d5060019c509a5050505050505050505050565b6000818152600260209081526040808320815160808101835290546fffffffffffffffffffffffffffffffff8116825263ffffffff700100000000000000000000000000000000820481169483018590527401000000000000000000000000000000000000000082041692820183905260ff780100000000000000000000000000000000000000000000000090910416151560608201528392909183610dca8383613cdb565b8451610de891906fffffffffffffffffffffffffffffffff16613d21565b606085015160019650909150835b83811015610f5957600081815260016020526040812090808085610e7057835460028501546f010000000000000000000000000000009091046effffffffffffffffffffffffffffff16906fffffffffffffffffffffffffffffffff80821691700100000000000000000000000000000000900416610eb6565b835460018501546effffffffffffffffffffffffffffff909116906fffffffffffffffffffffffffffffffff808216917001000000000000000000000000000000009004165b6fffffffffffffffffffffffffffffffff1692506fffffffffffffffffffffffffffffffff1692506effffffffffffffffffffffffffffff1692508a8015610efc575082155b8015610f085750600082115b9a508115610f3357610f1a8383613d35565b610f248883613d4d565b610f2e9190613d21565b610f36565b60005b610f40908d613d35565b9b50505050508080610f5190613d8a565b915050610df6565b505050505050915091565b600080600080610f7f8787610f776111e7565b886000612432565b5050915091506000821315610fd557610fd073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f16333085612b23565b611029565b60008212156110295761102933610feb84613dc3565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f169190612b87565b60008113156110795761107473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc216333084612b23565b6110cd565b60008112156110cd576110cd3361108f83613dc3565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2169190612b87565b90969095509350505050565b6000811561112357670de0b6b3a764000060016110f68587613d4d565b61110890670de0b6b3a7640000613d35565b6111129190613cdb565b61111c9190613d21565b9050611143565b670de0b6b3a76400006111368486613d4d565b6111409190613d21565b90505b9392505050565b815b6111568284613d35565b8110156111cd57600081815260016020526040902080547e01000000000000000000000000000000000000000000000000000000000000900461ffff1690601e61119f83613dfc565b91906101000a81548161ffff021916908361ffff1602179055505080806111c590613d8a565b91505061114c565b505050565b6111e46111de42612bdd565b8261114a565b50565b60008073773616e4d11a78f511299002da57a0a94577f1f473ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015611249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126d9190613e38565b50505091505060008112156112ae576040517f61ca76d200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b600080803373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ff1f2b4adb9df6fc8eafecdcbf96a2b3516804551614611326576040517f48f5c3ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061133186610d24565b9250905081156116665760008061134e60408b0160208c01613c41565b9050600161136260608c0160408d01613c8b565b600381111561137357611373613c5c565b141561139457506001905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25b6000888152600260205260409020547801000000000000000000000000000000000000000000000000900460ff166113ec577f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f61140e565b7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611472576040517f6c98dcaf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000a156114d4576127106114c77f000000000000000000000000000000000000000000000000000000000000000a86613d4d565b6114d19190613d21565b90505b6114de8185613cdb565b60008a815260026020526040902080547fffffffffffffff000000000000000000000000000000000000000000000000001690559650821561163b576040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810188905273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290632e1a7d4d90602401600060405180830381600087803b15801561158057600080fd5b505af1158015611594573d6000803e3d6000fd5b50506040517f12a53623000000000000000000000000000000000000000000000000000000008152600481018c90527f000000000000000000000000ff1f2b4adb9df6fc8eafecdcbf96a2b35168045573ffffffffffffffffffffffffffffffffffffffff1692506312a53623915089906024016000604051808303818588803b15801561162157600080fd5b505af1158015611635573d6000803e3d6000fd5b50505050505b80156116625761166273ffffffffffffffffffffffffffffffffffffffff83163283612b87565b5050505b5096509650969350505050565b6000806116a184847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610f64565b915091509250929050565b60008060006116b96111e7565b90506000806000806116d0600080878b6001612432565b93509350935093506000821180156116e85750600081115b15611706576116fb8282878b6001612432565b929650909450925090505b8115611934576040805160a081019091527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000007f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f606090811b821660c08401527d64000000000000000000000000000000000000000000000000000000000060d48401527fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000060d78401527e01f4000000000000000000000000000000000000000000000000000000000060eb8401527f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2901b1660ee82015260009073e592427a0aece92de3edee1f18e0157c058615649063c04b8d5990806101028101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152908252306020830152429082015260608101879052608001612710611876606482613cdb565b611882898d60006110d9565b61188c9190613d4d565b6118969190613d21565b8152506040518263ffffffff1660e01b81526004016118b59190613ef2565b6020604051808303816000875af11580156118d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f89190613f58565b905060008361190f83670de0b6b3a7640000613d4d565b6119199190613d21565b905061192a600083838d6001612432565b5091975095505050505b8015611b79576040805160a081019091527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000007f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2606090811b821660c08401527e01f4000000000000000000000000000000000000000000000000000000000060d48401527fa0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000060d78401527d64000000000000000000000000000000000000000000000000000000000060eb8401527f0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f901b1660ee82015260009073e592427a0aece92de3edee1f18e0157c058615649063c04b8d5990806101028101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152908252306020830152429082015260608101869052608001612710611aa4606482613cdb565b611ab0888d6000611d10565b611aba9190613d4d565b611ac49190613d21565b8152506040518263ffffffff1660e01b8152600401611ae39190613ef2565b6020604051808303816000875af1158015611b02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b269190613f58565b9050600081600181611b4086670de0b6b3a7640000613d4d565b611b4a9190613d35565b611b549190613cdb565b611b5e9190613d21565b9050611b6f826000838d6001612432565b5091975095505050505b5091969095509350505050565b611be36040805160e081018252600080825260208083018290528284018290528351808501855282815280820183905260608401528351808501909452818452830152906080820190815260006020820181905260409091015290565b50600090815260016020818152604092839020835160e08101855281546effffffffffffffffffffffffffffff80821683526f01000000000000000000000000000000820416828501527e01000000000000000000000000000000000000000000000000000000000000900461ffff168186015284518086018652938201546fffffffffffffffffffffffffffffffff808216865270010000000000000000000000000000000091829004811686860152606083019590955285518087019096526002830154808616875281900485169386019390935260808101949094526003015491821660a0840152900463ffffffff1660c082015290565b600080611d0a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6116ac565b50509091565b60008115611d385782600181611d2e87670de0b6b3a7640000613d4d565b6111089190613d35565b8261113685670de0b6b3a7640000613d4d565b6000805481908190611d6e9063ffffffff80821691640100000000900416612c26565b90506000611d9c7f000000000000000000000000000000000000000000000000000000000001518042613d21565b9050815b818111611e2557600081815260016020526040902054611dd1906effffffffffffffffffffffffffffff1686613d35565b600082815260016020526040902054909550611e11906f0100000000000000000000000000000090046effffffffffffffffffffffffffffff1685613d35565b935080611e1d81613d8a565b915050611da0565b5050509091565b801580611ecc57506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611ea6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eca9190613f58565b155b611f5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526111cd9084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612ca3565b60606111408484600085612daf565b600061204b42612bdd565b9050818015612060575060005463ffffffff16155b156120a45761206e81612f45565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff929092169190911790555b811580156120c05750600054640100000000900463ffffffff16155b156120ef576120ce81612f45565b600060046101000a81548163ffffffff021916908363ffffffff1602179055505b6120ff6120fa6111e7565b612fb9565b6001600061210d8285613cdb565b815260200190815260200160002060030160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555061215d42612f45565b6001600061216b8285613cdb565b815260200190815260200160002060030160106101000a81548163ffffffff021916908363ffffffff160217905550600083856121a89190613d21565b9050815b6121b68584613d35565b8110156122c6578315612234576121cc82613035565b600082815260016020526040812080549091906121fb9084906effffffffffffffffffffffffffffff16613f71565b92506101000a8154816effffffffffffffffffffffffffffff02191690836effffffffffffffffffffffffffffff1602179055506122b4565b61223d82613035565b60008281526001602052604090208054600f9061227f9084906f0100000000000000000000000000000090046effffffffffffffffffffffffffffff16613f71565b92506101000a8154816effffffffffffffffffffffffffffff02191690836effffffffffffffffffffffffffffff1602179055505b806122be81613d8a565b9150506121ac565b5060405180608001604052806122db87612fb9565b6fffffffffffffffffffffffffffffffff1681526020016122fb84612f45565b63ffffffff1681526020016123186123138786613d35565b612f45565b63ffffffff908116825294151560209182015260009788526002815260409788902082518154928401519984015160609094015115157801000000000000000000000000000000000000000000000000027fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff9488167401000000000000000000000000000000000000000002949094167fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff9a909716700100000000000000000000000000000000027fffffffffffffffffffffffff00000000000000000000000000000000000000009093166fffffffffffffffffffffffffffffffff909116179190911797909716939093179290921790945550505050565b6000806000806124a3604051806101a00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b8781526000805463ffffffff8082166020850181905264010000000090920416604084018190526124d49190612c26565b60008181526001602081815260408320600301546fffffffffffffffffffffffffffffffff8116610120880190815293859052919052700100000000000000000000000000000000900463ffffffff16610140850152519091506125a557805b6101208301516125a3578061254881613fa4565b60008181526001602081815260408320600301546fffffffffffffffffffffffffffffffff81166101208a01529284905252700100000000000000000000000000000000900463ffffffff1661014086015291506125349050565b505b6125b58b836000015160006110d9565b606083015281516125c9908b906000611d10565b608083015260006125d942612bdd565b90506125e88360000151612fb9565b600160006125f68285613cdb565b815260200190815260200160002060030160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555061264642612f45565b600160006126548285613cdb565b81526020810191909152604001600020600301805463ffffffff92909216700100000000000000000000000000000000027fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff909216919091179055815b6126bb828b6130b0565b811015612a2a57600081815260016020818152604092839020835160e08101855281546effffffffffffffffffffffffffffff80821683526f01000000000000000000000000000000820416828501527e01000000000000000000000000000000000000000000000000000000000000900461ffff168186015284518086018652938201546fffffffffffffffffffffffffffffffff808216865270010000000000000000000000000000000091829004811686860152606083019590955285518087019096526002830154808616875281900485169386019390935260808101949094526003015491821660a0840152900463ffffffff1660c08201526127c48582846130c5565b6127cf85828c6134bf565b6127da85828c61366c565b80516effffffffffffffffffffffffffffff161580156127fd5750818560200151145b15612819576001856020018181516128159190613d35565b9052505b60208101516effffffffffffffffffffffffffffff1615801561283f5750818560400151145b1561285b576001856040018181516128579190613d35565b9052505b80600001516effffffffffffffffffffffffffffff1685610160018181516128839190613d35565b9052506020810151610180860180516effffffffffffffffffffffffffffff909216916128b1908390613d35565b90525060008281526001602081815260409283902084518154838701519587015161ffff167e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6effffffffffffffffffffffffffffff9788166f01000000000000000000000000000000027fffff0000000000000000000000000000000000000000000000000000000000009093169790931696909617171693909317835560608401518051908201516fffffffffffffffffffffffffffffffff9081167001000000000000000000000000000000009081029282169290921793850193909355608085015180519201518316810291831691909117600284015560a08401516003909301805460c09095015163ffffffff169091027fffffffffffffffffffffffff0000000000000000000000000000000000000000909416929091169190911791909117905580612a2281613d8a565b9150506126b1565b50600054602084015163ffffffff9091161015612a8457612a4e8360200151612f45565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff929092169190911790555b600054604084015164010000000090910463ffffffff161015612acf57612aae8360400151612f45565b600060046101000a81548163ffffffff021916908363ffffffff1602179055505b60008360a001518460e00151612ae59190613fd9565b905060008460c00151856101000151612afe9190613fd9565b61016086015161018090960151929f909e50949c50909a509298505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052612b819085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611faf565b50505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526111cd9084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611faf565b60007f00000000000000000000000000000000000000000000000000000000000151806001612c0c8285613d35565b612c169190613cdb565b612c209190613d21565b92915050565b60008083158015612c35575082155b15612c6c576040517f1562001c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612c768385613d4d565b612c8e57828411612c87578261111c565b5082611143565b828410612c9b5782611140565b509192915050565b6000612d05826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120319092919063ffffffff16565b8051909150156111cd5780806020019051810190612d23919061404d565b6111cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611f54565b606082471015612e41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611f54565b73ffffffffffffffffffffffffffffffffffffffff85163b612ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611f54565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612ee8919061406a565b60006040518083038185875af1925050503d8060008114612f25576040519150601f19603f3d011682016040523d82523d6000602084013e612f2a565b606091505b5091509150612f3a828286613807565b979650505050505050565b600063ffffffff821115612fb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f4f766572666c6f770000000000000000000000000000000000000000000000006044820152606401611f54565b5090565b60006fffffffffffffffffffffffffffffffff821115612fb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f4f766572666c6f770000000000000000000000000000000000000000000000006044820152606401611f54565b60006effffffffffffffffffffffffffffff821115612fb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f4f766572666c6f770000000000000000000000000000000000000000000000006044820152606401611f54565b60008183116130bf5782611143565b50919050565b81516effffffffffffffffffffffffffffff16158015906130fb5750600082602001516effffffffffffffffffffffffffffff16115b156111cd5760a08201516fffffffffffffffffffffffffffffffff16801561313b57610120840181905260c083015163ffffffff16610140850152613218565b60008461014001514261314e9190613cdb565b61012086015186516131609190613fd9565b61316a9190614086565b9050600085610140015160027f00000000000000000000000000000000000000000000000000000000000151806131a19190613d21565b6131cb7f000000000000000000000000000000000000000000000000000000000001518087613d4d565b6131d59190613d35565b6131df9190613cdb565b905060006131ed82846140ee565b8761012001516131fd91906141aa565b9050600081136132105760009350613214565b8093505b5050505b600061323e6120fa85600001516effffffffffffffffffffffffffffff168460006110d9565b905083602001516effffffffffffffffffffffffffffff16816fffffffffffffffffffffffffffffffff1611156133ac5760006132956120fa86602001516effffffffffffffffffffffffffffff16856000611d10565b905084602001516effffffffffffffffffffffffffffff1685606001516020018181516132c2919061421e565b6fffffffffffffffffffffffffffffffff16905250606085015180518291906132ec90839061421e565b6fffffffffffffffffffffffffffffffff169052506080850151602001805182919061331990839061421e565b6fffffffffffffffffffffffffffffffff169052506020850151608086015180516effffffffffffffffffffffffffffff9092169161335990839061421e565b6fffffffffffffffffffffffffffffffff90811690915261337c91508216613035565b8551869061338b908390614249565b6effffffffffffffffffffffffffffff1690525050600060208501526134b8565b83600001516effffffffffffffffffffffffffffff1684608001516020018181516133d7919061421e565b6fffffffffffffffffffffffffffffffff169052506080840151805182919061340190839061421e565b6fffffffffffffffffffffffffffffffff169052506060840151602001805182919061342e90839061421e565b6fffffffffffffffffffffffffffffffff169052508351606085015180516effffffffffffffffffffffffffffff9092169161346b90839061421e565b6fffffffffffffffffffffffffffffffff9081169091526000865261349291508216613035565b846020018181516134a39190614249565b6effffffffffffffffffffffffffffff169052505b5050505050565b600083606001511180156134e85750600082602001516effffffffffffffffffffffffffffff16115b156111cd5760006134fc8460600151612fb9565b905082602001516effffffffffffffffffffffffffffff1684606001511115613537575060208201516effffffffffffffffffffffffffffff165b600061355e6120fa836fffffffffffffffffffffffffffffffff1687600001518615611d10565b905061357b826fffffffffffffffffffffffffffffffff16613035565b8460200181815161358c9190614249565b6effffffffffffffffffffffffffffff16905250608084015180518391906135b590839061421e565b6fffffffffffffffffffffffffffffffff16905250608084015160200180518291906135e290839061421e565b6fffffffffffffffffffffffffffffffff908116909152606087018051918516925090613610908390613cdb565b90525060c0850180516fffffffffffffffffffffffffffffffff84169190613639908390613d35565b90525060e0850180516fffffffffffffffffffffffffffffffff83169190613662908390613d35565b9052505050505050565b60008360800151118015613691575081516effffffffffffffffffffffffffffff1615155b156111cd5760006136a58460800151612fb9565b905082600001516effffffffffffffffffffffffffffff16846080015111156136dd575081516effffffffffffffffffffffffffffff165b60006137046120fa836fffffffffffffffffffffffffffffffff16876000015186156110d9565b9050613721826fffffffffffffffffffffffffffffffff16613035565b84518590613730908390614249565b6effffffffffffffffffffffffffffff169052506060840151805183919061375990839061421e565b6fffffffffffffffffffffffffffffffff169052506060840151602001805182919061378690839061421e565b6fffffffffffffffffffffffffffffffff9081169091526080870180519185169250906137b4908390613cdb565b90525060a0850180516fffffffffffffffffffffffffffffffff841691906137dd908390613d35565b905250610100850180516fffffffffffffffffffffffffffffffff83169190613662908390613d35565b60608315613816575081611143565b8251156138265782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f549190614279565b6000606082840312156130bf57600080fd5b803567ffffffffffffffff811681146112ae57600080fd5b803573ffffffffffffffffffffffffffffffffffffffff811681146112ae57600080fd5b600080600080600080600080610200898b0312156138c557600080fd5b6138cf8a8a61385a565b97506138de8a60608b0161385a565b96506138ed8a60c08b0161385a565b95506138fd8a6101208b0161385a565b945061018089013593506101a0890135925061391c6101c08a0161386c565b915061392b6101e08a01613884565b90509295985092959890939650565b60006020828403121561394c57600080fd5b5035919050565b60008060006060848603121561396857600080fd5b505081359360208301359350604090920135919050565b80151581146111e457600080fd5b6000806000606084860312156139a257600080fd5b833592506020840135915060408401356139bb8161397f565b809150509250925092565b6effffffffffffffffffffffffffffff88811682528716602082015261ffff861660408201526101208101613a1d606083018780516fffffffffffffffffffffffffffffffff908116835260209182015116910152565b84516fffffffffffffffffffffffffffffffff90811660a084015260208601511660c08301526fffffffffffffffffffffffffffffffff841660e083015263ffffffff831661010083015298975050505050505050565b60008060408385031215613a8757600080fd5b50508035926020909101359150565b6000806000806000806101c08789031215613ab057600080fd5b613aba888861385a565b9550613ac9886060890161385a565b9450613ad88860c0890161385a565b9350613ae888610120890161385a565b92506101808701359150613aff6101a0880161386c565b90509295509295509295565b6000610120820190506effffffffffffffffffffffffffffff8084511683528060208501511660208401525061ffff60408401511660408301526060830151613b76606084018280516fffffffffffffffffffffffffffffffff908116835260209182015116910152565b50608083015180516fffffffffffffffffffffffffffffffff90811660a085015260208201511660c08401525060a08301516fffffffffffffffffffffffffffffffff1660e083015260c09092015163ffffffff166101009091015290565b60008060008060006101a08688031215613bee57600080fd5b613bf8878761385a565b9450613c07876060880161385a565b9350613c168760c0880161385a565b9250613c2687610120880161385a565b9150613c35610180870161386c565b90509295509295909350565b600060208284031215613c5357600080fd5b61114382613884565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215613c9d57600080fd5b81356004811061114357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613ced57613ced613cac565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613d3057613d30613cf2565b500490565b60008219821115613d4857613d48613cac565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613d8557613d85613cac565b500290565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613dbc57613dbc613cac565b5060010190565b60007f8000000000000000000000000000000000000000000000000000000000000000821415613df557613df5613cac565b5060000390565b600061ffff80831681811415613e1457613e14613cac565b6001019392505050565b805169ffffffffffffffffffff811681146112ae57600080fd5b600080600080600060a08688031215613e5057600080fd5b613e5986613e1e565b9450602086015193506040860151925060608601519150613c3560808701613e1e565b60005b83811015613e97578181015183820152602001613e7f565b83811115612b815750506000910152565b60008151808452613ec0816020860160208601613e7c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000825160a06020840152613f0e60c0840182613ea8565b905073ffffffffffffffffffffffffffffffffffffffff60208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b600060208284031215613f6a57600080fd5b5051919050565b60006effffffffffffffffffffffffffffff808316818516808303821115613f9b57613f9b613cac565b01949350505050565b600081613fb357613fb3613cac565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561401357614013613cac565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561404757614047613cac565b50500390565b60006020828403121561405f57600080fd5b81516111438161397f565b6000825161407c818460208701613e7c565b9190910192915050565b60008261409557614095613cf2565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156140e9576140e9613cac565b500590565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561412f5761412f613cac565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561416a5761416a613cac565b6000871292508782058712848416161561418657614186613cac565b8785058712818416161561419c5761419c613cac565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156141e4576141e4613cac565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561421857614218613cac565b50500190565b60006fffffffffffffffffffffffffffffffff808316818516808303821115613f9b57613f9b613cac565b60006effffffffffffffffffffffffffffff8381169083168181101561427157614271613cac565b039392505050565b6020815260006111436020830184613ea856fea2646970667358221220dadb774879862d74b0e99a5df4951bbca87781aba24dabf096b57c8b2786c66a64736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ff1f2b4adb9df6fc8eafecdcbf96a2b3516804550000000000000000000000000000000000000000000000000000000000015180000000000000000000000000000000000000000000000000000000000000000a
-----Decoded View---------------
Arg [0] : _rollupProcessor (address): 0xFF1F2B4ADb9dF6FC8eAFecDcbF96A2B351680455
Arg [1] : _tickSize (uint256): 86400
Arg [2] : _fee (uint256): 10
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000ff1f2b4adb9df6fc8eafecdcbf96a2b351680455
Arg [1] : 0000000000000000000000000000000000000000000000000000000000015180
Arg [2] : 000000000000000000000000000000000000000000000000000000000000000a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.