ETH Price: $3,087.77 (-0.02%)
Gas: 5 Gwei

Contract

0xE57c868F97E8c1DEAF24DC72b89D886EBFa24D9f
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
0x60c06040199251612024-05-22 11:36:1148 days ago1716377771IN
 Create: AlicePositionLib
0 ETH0.01805359.7419202

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AlicePositionLib

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 16 : AlicePositionLib.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.
    (c) Enzyme Foundation <[email protected]>
    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity 0.8.19;

import {Address} from "openzeppelin-solc-0.8/utils/Address.sol";
import {IAliceOrderManager} from "../../../../../external-interfaces/IAliceOrderManager.sol";
import {IERC20} from "../../../../../external-interfaces/IERC20.sol";
import {IWETH} from "../../../../../external-interfaces/IWETH.sol";
import {AddressArrayLib} from "../../../../../utils/0.8.19/AddressArrayLib.sol";
import {Uint256ArrayLib} from "../../../../../utils/0.8.19/Uint256ArrayLib.sol";
import {AssetHelpers} from "../../../../../utils/0.8.19/AssetHelpers.sol";
import {WrappedSafeERC20 as SafeERC20} from "../../../../../utils/0.8.19/open-zeppelin/WrappedSafeERC20.sol";
import {AlicePositionLibBase1} from "./bases/AlicePositionLibBase1.sol";
import {IAlicePosition} from "./IAlicePosition.sol";

/// @title AlicePositionLib Contract
/// @author Enzyme Foundation <[email protected]>
/// @notice An External Position library contract for Alice positions
contract AlicePositionLib is IAlicePosition, AlicePositionLibBase1, AssetHelpers {
    using AddressArrayLib for address[];
    using SafeERC20 for IERC20;
    using Uint256ArrayLib for uint256[];

    address private constant ALICE_NATIVE_ASSET_ADDRESS = 0x0000000000000000000000000000000000000000;
    IAliceOrderManager private immutable ALICE_ORDER_MANAGER;
    IWETH private immutable WRAPPED_NATIVE_TOKEN;

    error InvalidActionId();

    error OrderNotSettledOrCancelled();

    constructor(address _aliceOrderManagerAddress, address _wrappedNativeAssetAddress) {
        ALICE_ORDER_MANAGER = IAliceOrderManager(_aliceOrderManagerAddress);
        WRAPPED_NATIVE_TOKEN = IWETH(_wrappedNativeAssetAddress);
    }

    /// @notice Initializes the external position
    /// @dev Nothing to initialize for this contract
    function init(bytes memory) external override {}

    /// @notice Receives and executes a call from the Vault
    /// @param _actionData Encoded data to execute the action
    function receiveCallFromVault(bytes memory _actionData) external override {
        (uint256 actionId, bytes memory actionArgs) = abi.decode(_actionData, (uint256, bytes));

        if (actionId == uint256(Actions.PlaceOrder)) {
            __placeOrder(actionArgs);
        } else if (actionId == uint256(Actions.Sweep)) {
            __sweep(actionArgs);
        } else if (actionId == uint256(Actions.RefundOrder)) {
            __refundOrder(actionArgs);
        } else {
            revert InvalidActionId();
        }
    }

    /// @dev Helper to place an order on the Alice Order Manager
    function __placeOrder(bytes memory _actionArgs) private {
        IAlicePosition.PlaceOrderActionArgs memory placeOrderArgs =
            abi.decode(_actionArgs, (IAlicePosition.PlaceOrderActionArgs));

        IAliceOrderManager.Instrument memory instrument =
            ALICE_ORDER_MANAGER.getInstrument(placeOrderArgs.instrumentId, true);

        address outgoingAssetAddress = placeOrderArgs.isBuyOrder ? instrument.quote : instrument.base;
        address incomingAssetAddress = placeOrderArgs.isBuyOrder ? instrument.base : instrument.quote;

        uint256 nativeAssetAmount;
        if (outgoingAssetAddress == ALICE_NATIVE_ASSET_ADDRESS) {
            // If spendAsset is the native asset, unwrap WETH.
            nativeAssetAmount = placeOrderArgs.quantityToSell;
            WRAPPED_NATIVE_TOKEN.withdraw(placeOrderArgs.quantityToSell);
        } else {
            // Approve the spend asset
            IERC20(outgoingAssetAddress).safeApprove({
                _spender: address(ALICE_ORDER_MANAGER),
                _value: placeOrderArgs.quantityToSell
            });
        }

        // Place the order
        ALICE_ORDER_MANAGER.placeOrder{value: nativeAssetAmount}({
            _instrumentId: placeOrderArgs.instrumentId,
            _isBuyOrder: placeOrderArgs.isBuyOrder,
            _quantityToSell: placeOrderArgs.quantityToSell,
            _limitAmountToGet: placeOrderArgs.limitAmountToGet
        });

        __addOrder({
            _orderDetails: OrderDetails({
                outgoingAssetAddress: outgoingAssetAddress,
                incomingAssetAddress: incomingAssetAddress,
                outgoingAmount: placeOrderArgs.quantityToSell
            })
        });
    }

    /// @dev Helper to sweep balance from settled or cancelled orders and clear storage
    function __sweep(bytes memory _actionsArgs) private {
        IAlicePosition.SweepActionArgs memory sweepArgs = abi.decode(_actionsArgs, (IAlicePosition.SweepActionArgs));

        for (uint256 i; i < sweepArgs.orderIds.length; i++) {
            uint256 orderId = sweepArgs.orderIds[i];

            if (!__isOrderSettledOrCancelled({_orderId: orderId})) {
                revert OrderNotSettledOrCancelled();
            }

            OrderDetails memory orderDetails = getOrderDetails({_orderId: orderId});

            __removeOrder({_orderId: orderId});

            // If the order is settled or cancelled, the EP could have received:
            // The incomingAsset if the order has been settled
            // The outgoingAsset if the order has been cancelled
            __retrieveAssetBalance({_asset: IERC20(orderDetails.incomingAssetAddress)});
            __retrieveAssetBalance({_asset: IERC20(orderDetails.outgoingAssetAddress)});
        }
    }

    /// @dev Helper to refund an outstanding order
    function __refundOrder(bytes memory _actionsArgs) private {
        IAlicePosition.RefundOrderActionArgs memory refundOrderArgs =
            abi.decode(_actionsArgs, (IAlicePosition.RefundOrderActionArgs));

        OrderDetails memory orderDetails = getOrderDetails({_orderId: refundOrderArgs.orderId});

        // Remove the order from storage
        __removeOrder({_orderId: refundOrderArgs.orderId});

        // Refund the order
        ALICE_ORDER_MANAGER.refundOrder({
            _orderId: refundOrderArgs.orderId,
            _user: address(this),
            _instrumentId: refundOrderArgs.instrumentId,
            _isBuyOrder: refundOrderArgs.isBuyOrder,
            _quantityToSell: refundOrderArgs.quantityToSell,
            _limitAmountToGet: refundOrderArgs.limitAmountToGet,
            _timestamp: refundOrderArgs.timestamp
        });

        // Return the refunded outgoing asset back to the vault
        IERC20 outgoingAsset = IERC20(orderDetails.outgoingAssetAddress);

        if (address(outgoingAsset) == ALICE_NATIVE_ASSET_ADDRESS) {
            Address.sendValue(payable(msg.sender), address(this).balance);
        } else {
            outgoingAsset.safeTransfer(msg.sender, outgoingAsset.balanceOf(address(this)));
        }
    }

    /// @dev Helper to add the orderId to storage
    function __addOrder(OrderDetails memory _orderDetails) private {
        uint256 orderId = ALICE_ORDER_MANAGER.getMostRecentOrderId();

        orderIds.push(orderId);
        orderIdToOrderDetails[orderId] = _orderDetails;

        emit OrderIdAdded(orderId, _orderDetails);
    }

    /// @dev Helper to check whether an order has settled or been cancelled
    function __isOrderSettledOrCancelled(uint256 _orderId) private view returns (bool isSettledOrCancelled_) {
        // When an order has been settled or cancelled, its orderHash getter will throw
        try ALICE_ORDER_MANAGER.getOrderHash({_orderId: _orderId}) {
            return false;
        } catch {
            return true;
        }
    }

    /// @dev Helper to remove the orderId from storage
    function __removeOrder(uint256 _orderId) private {
        orderIds.removeStorageItem(_orderId);

        // Reset the mapping
        delete orderIdToOrderDetails[_orderId];

        emit OrderIdRemoved(_orderId);
    }

    /// @dev Helper to send the balance of an Alice order asset to the Vault
    function __retrieveAssetBalance(IERC20 _asset) private {
        uint256 balance =
            address(_asset) == ALICE_NATIVE_ASSET_ADDRESS ? address(this).balance : _asset.balanceOf(address(this));

        if (balance > 0) {
            // Transfer the asset
            if (address(_asset) == ALICE_NATIVE_ASSET_ADDRESS) {
                Address.sendValue(payable(msg.sender), balance);
            } else {
                _asset.safeTransfer(msg.sender, balance);
            }
        }
    }

    ////////////////////
    // POSITION VALUE //
    ////////////////////

    /// @notice Retrieves the debt assets (negative value) of the external position
    /// @return assets_ Debt assets
    /// @return amounts_ Debt asset amounts
    function getDebtAssets() external view override returns (address[] memory assets_, uint256[] memory amounts_) {}

    /// @notice Retrieves the managed assets (positive value) of the external position
    /// @return assets_ Managed assets
    /// @return amounts_ Managed asset amounts
    /// @dev There are 2 ways that positive value can be contributed to this position
    /// 1. Tokens held by the EP either as a result of order settlements or as a result of order cancellations
    /// 2. Tokens held in pending (unfulfilled and uncancelled) orders
    function getManagedAssets() external view override returns (address[] memory assets_, uint256[] memory amounts_) {
        uint256[] memory orderIdsMem = getOrderIds();

        address[] memory receivableAssets;

        for (uint256 i; i < orderIdsMem.length; i++) {
            OrderDetails memory orderDetails = getOrderDetails({_orderId: orderIdsMem[i]});

            bool settledOrCancelled = __isOrderSettledOrCancelled({_orderId: orderIdsMem[i]});

            // If the order is settled or cancelled, the EP will have received the incomingAsset or the outgoingAsset
            // Incoming assets can be received through order settlements
            // Outgoing assets can be received back through order cancellations
            // We have no way of differentiating between the two, so we must add both to the expected assets
            if (settledOrCancelled) {
                receivableAssets = receivableAssets.addUniqueItem(orderDetails.outgoingAssetAddress);
                receivableAssets = receivableAssets.addUniqueItem(orderDetails.incomingAssetAddress);
            } else {
                // If the order is not settled, value the position for its refundable value
                assets_ = assets_.addItem(
                    orderDetails.outgoingAssetAddress == ALICE_NATIVE_ASSET_ADDRESS
                        ? address(WRAPPED_NATIVE_TOKEN)
                        : orderDetails.outgoingAssetAddress
                );
                amounts_ = amounts_.addItem(orderDetails.outgoingAmount);
            }
        }

        // Check the balance EP balance of each asset that could be received
        for (uint256 i; i < receivableAssets.length; i++) {
            address receivableAssetAddress = receivableAssets[i];

            uint256 balance = receivableAssetAddress == ALICE_NATIVE_ASSET_ADDRESS
                ? address(this).balance
                : IERC20(receivableAssetAddress).balanceOf(address(this));

            if (balance == 0) {
                continue;
            }

            assets_ = assets_.addItem(
                receivableAssetAddress == ALICE_NATIVE_ASSET_ADDRESS
                    ? address(WRAPPED_NATIVE_TOKEN)
                    : receivableAssetAddress
            );
            amounts_ = amounts_.addItem(balance);
        }

        return __aggregateAssetAmounts({_rawAssets: assets_, _rawAmounts: amounts_});
    }

    ///////////////////
    // STATE GETTERS //
    ///////////////////

    /// @notice Get the orderDetails of a specified orderId
    /// @return orderDetails_ The orderDetails
    function getOrderDetails(uint256 _orderId) public view override returns (OrderDetails memory orderDetails_) {
        return orderIdToOrderDetails[_orderId];
    }

    /// @notice Get the pending orderIds of the external position
    /// @return orderIds_ The orderIds
    function getOrderIds() public view override returns (uint256[] memory orderIds_) {
        return orderIds;
    }
}

File 2 of 16 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.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 functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 3 of 16 : IAliceOrderManager.sol
/*
    This file is part of the Enzyme Protocol.

    (c) Enzyme Foundation <[email protected]>

    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.9.0;

/// @title IAliceOrderManager Interface
/// @author Enzyme Foundation <[email protected]>
interface IAliceOrderManager {
    struct Instrument {
        uint16 id;
        bool enabled;
        address base;
        address quote;
    }

    function getInstrument(uint16 _instrumentId, bool _mustBeActive)
        external
        view
        returns (Instrument memory instrument_);

    function getMostRecentOrderId() external view returns (uint256 orderId_);

    function getOrderHash(uint256 _orderId) external view returns (bytes32 orderHash_);

    function placeOrder(uint16 _instrumentId, bool _isBuyOrder, uint256 _quantityToSell, uint256 _limitAmountToGet)
        external
        payable;

    function refundOrder(
        uint256 _orderId,
        address _user,
        uint16 _instrumentId,
        bool _isBuyOrder,
        uint256 _quantityToSell,
        uint256 _limitAmountToGet,
        uint256 _timestamp
    ) external;
}

File 4 of 16 : IERC20.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.9.0;

/// @title IERC20 Interface
/// @author Enzyme Council <[email protected]>
interface IERC20 {
    // IERC20 - strict

    function allowance(address _owner, address _spender) external view returns (uint256 allowance_);

    function approve(address _spender, uint256 _value) external returns (bool approve_);

    function balanceOf(address _account) external view returns (uint256 balanceOf_);

    function totalSupply() external view returns (uint256 totalSupply_);

    function transfer(address _to, uint256 _value) external returns (bool transfer_);

    function transferFrom(address _from, address _to, uint256 _value) external returns (bool transferFrom_);

    // IERC20 - typical

    function decimals() external view returns (uint8 decimals_);

    function name() external view returns (string memory name_);

    function symbol() external view returns (string memory symbol_);
}

File 5 of 16 : IWETH.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.

    (c) Enzyme Council <[email protected]>

    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity >=0.6.0 <0.9.0;

/// @title IWETH Interface
/// @author Enzyme Council <[email protected]>
interface IWETH {
    function deposit() external payable;

    function withdraw(uint256) external;
}

File 6 of 16 : AddressArrayLib.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.

    (c) Enzyme Council <[email protected]>

    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity 0.8.19;

/// @title AddressArray Library
/// @author Enzyme Council <[email protected]>
/// @notice A library to extend the address array data type
library AddressArrayLib {
    /////////////
    // STORAGE //
    /////////////

    /// @dev Helper to remove an item from a storage array
    function removeStorageItem(address[] storage _self, address _itemToRemove) internal returns (bool removed_) {
        uint256 itemCount = _self.length;
        for (uint256 i; i < itemCount; i++) {
            if (_self[i] == _itemToRemove) {
                if (i < itemCount - 1) {
                    _self[i] = _self[itemCount - 1];
                }
                _self.pop();
                removed_ = true;
                break;
            }
        }

        return removed_;
    }

    /// @dev Helper to verify if a storage array contains a particular value
    function storageArrayContains(address[] storage _self, address _target) internal view returns (bool doesContain_) {
        uint256 arrLength = _self.length;
        for (uint256 i; i < arrLength; i++) {
            if (_target == _self[i]) {
                return true;
            }
        }
        return false;
    }

    ////////////
    // MEMORY //
    ////////////

    /// @dev Helper to add an item to an array. Does not assert uniqueness of the new item.
    function addItem(address[] memory _self, address _itemToAdd) internal pure returns (address[] memory nextArray_) {
        nextArray_ = new address[](_self.length + 1);
        for (uint256 i; i < _self.length; i++) {
            nextArray_[i] = _self[i];
        }
        nextArray_[_self.length] = _itemToAdd;

        return nextArray_;
    }

    /// @dev Helper to add an item to an array, only if it is not already in the array.
    function addUniqueItem(address[] memory _self, address _itemToAdd)
        internal
        pure
        returns (address[] memory nextArray_)
    {
        if (contains(_self, _itemToAdd)) {
            return _self;
        }

        return addItem(_self, _itemToAdd);
    }

    /// @dev Helper to verify if an array contains a particular value
    function contains(address[] memory _self, address _target) internal pure returns (bool doesContain_) {
        for (uint256 i; i < _self.length; i++) {
            if (_target == _self[i]) {
                return true;
            }
        }
        return false;
    }

    /// @dev Helper to merge the unique items of a second array.
    /// Does not consider uniqueness of either array, only relative uniqueness.
    /// Preserves ordering.
    function mergeArray(address[] memory _self, address[] memory _arrayToMerge)
        internal
        pure
        returns (address[] memory nextArray_)
    {
        uint256 newUniqueItemCount;
        for (uint256 i; i < _arrayToMerge.length; i++) {
            if (!contains(_self, _arrayToMerge[i])) {
                newUniqueItemCount++;
            }
        }

        if (newUniqueItemCount == 0) {
            return _self;
        }

        nextArray_ = new address[](_self.length + newUniqueItemCount);
        for (uint256 i; i < _self.length; i++) {
            nextArray_[i] = _self[i];
        }
        uint256 nextArrayIndex = _self.length;
        for (uint256 i; i < _arrayToMerge.length; i++) {
            if (!contains(_self, _arrayToMerge[i])) {
                nextArray_[nextArrayIndex] = _arrayToMerge[i];
                nextArrayIndex++;
            }
        }

        return nextArray_;
    }

    /// @dev Helper to verify if array is a set of unique values.
    /// Does not assert length > 0.
    function isUniqueSet(address[] memory _self) internal pure returns (bool isUnique_) {
        if (_self.length <= 1) {
            return true;
        }

        uint256 arrayLength = _self.length;
        for (uint256 i; i < arrayLength; i++) {
            for (uint256 j = i + 1; j < arrayLength; j++) {
                if (_self[i] == _self[j]) {
                    return false;
                }
            }
        }

        return true;
    }

    /// @dev Helper to remove items from an array. Removes all matching occurrences of each item.
    /// Does not assert uniqueness of either array.
    function removeItems(address[] memory _self, address[] memory _itemsToRemove)
        internal
        pure
        returns (address[] memory nextArray_)
    {
        if (_itemsToRemove.length == 0) {
            return _self;
        }

        bool[] memory indexesToRemove = new bool[](_self.length);
        uint256 remainingItemsCount = _self.length;
        for (uint256 i; i < _self.length; i++) {
            if (contains(_itemsToRemove, _self[i])) {
                indexesToRemove[i] = true;
                remainingItemsCount--;
            }
        }

        if (remainingItemsCount == _self.length) {
            nextArray_ = _self;
        } else if (remainingItemsCount > 0) {
            nextArray_ = new address[](remainingItemsCount);
            uint256 nextArrayIndex;
            for (uint256 i; i < _self.length; i++) {
                if (!indexesToRemove[i]) {
                    nextArray_[nextArrayIndex] = _self[i];
                    nextArrayIndex++;
                }
            }
        }

        return nextArray_;
    }
}

File 7 of 16 : Uint256ArrayLib.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.

    (c) Enzyme Council <[email protected]>

    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity 0.8.19;

/// @title Uint256Array Library
/// @author Enzyme Council <[email protected]>
/// @notice A library to extend the uint256 array data type
library Uint256ArrayLib {
    /////////////
    // STORAGE //
    /////////////

    /// @dev Helper to remove an item from a storage array
    function removeStorageItem(uint256[] storage _self, uint256 _itemToRemove) internal returns (bool removed_) {
        uint256 itemCount = _self.length;
        for (uint256 i; i < itemCount; i++) {
            if (_self[i] == _itemToRemove) {
                if (i < itemCount - 1) {
                    _self[i] = _self[itemCount - 1];
                }
                _self.pop();
                removed_ = true;
                break;
            }
        }

        return removed_;
    }

    /// @dev Helper to verify if a storage array contains a particular value
    function storageArrayContains(uint256[] storage _self, uint256 _target) internal view returns (bool doesContain_) {
        uint256 arrLength = _self.length;
        for (uint256 i; i < arrLength; i++) {
            if (_target == _self[i]) {
                return true;
            }
        }
        return false;
    }

    ////////////
    // MEMORY //
    ////////////

    /// @dev Helper to add an item to an array. Does not assert uniqueness of the new item.
    function addItem(uint256[] memory _self, uint256 _itemToAdd) internal pure returns (uint256[] memory nextArray_) {
        nextArray_ = new uint256[](_self.length + 1);
        for (uint256 i; i < _self.length; i++) {
            nextArray_[i] = _self[i];
        }
        nextArray_[_self.length] = _itemToAdd;

        return nextArray_;
    }

    /// @dev Helper to add an item to an array, only if it is not already in the array.
    function addUniqueItem(uint256[] memory _self, uint256 _itemToAdd)
        internal
        pure
        returns (uint256[] memory nextArray_)
    {
        if (contains(_self, _itemToAdd)) {
            return _self;
        }

        return addItem(_self, _itemToAdd);
    }

    /// @dev Helper to verify if an array contains a particular value
    function contains(uint256[] memory _self, uint256 _target) internal pure returns (bool doesContain_) {
        for (uint256 i; i < _self.length; i++) {
            if (_target == _self[i]) {
                return true;
            }
        }
        return false;
    }

    /// @dev Helper to merge the unique items of a second array.
    /// Does not consider uniqueness of either array, only relative uniqueness.
    /// Preserves ordering.
    function mergeArray(uint256[] memory _self, uint256[] memory _arrayToMerge)
        internal
        pure
        returns (uint256[] memory nextArray_)
    {
        uint256 newUniqueItemCount;
        for (uint256 i; i < _arrayToMerge.length; i++) {
            if (!contains(_self, _arrayToMerge[i])) {
                newUniqueItemCount++;
            }
        }

        if (newUniqueItemCount == 0) {
            return _self;
        }

        nextArray_ = new uint256[](_self.length + newUniqueItemCount);
        for (uint256 i; i < _self.length; i++) {
            nextArray_[i] = _self[i];
        }
        uint256 nextArrayIndex = _self.length;
        for (uint256 i; i < _arrayToMerge.length; i++) {
            if (!contains(_self, _arrayToMerge[i])) {
                nextArray_[nextArrayIndex] = _arrayToMerge[i];
                nextArrayIndex++;
            }
        }

        return nextArray_;
    }

    /// @dev Helper to verify if array is a set of unique values.
    /// Does not assert length > 0.
    function isUniqueSet(uint256[] memory _self) internal pure returns (bool isUnique_) {
        if (_self.length <= 1) {
            return true;
        }

        uint256 arrayLength = _self.length;
        for (uint256 i; i < arrayLength; i++) {
            for (uint256 j = i + 1; j < arrayLength; j++) {
                if (_self[i] == _self[j]) {
                    return false;
                }
            }
        }

        return true;
    }

    /// @dev Helper to remove items from an array. Removes all matching occurrences of each item.
    /// Does not assert uniqueness of either array.
    function removeItems(uint256[] memory _self, uint256[] memory _itemsToRemove)
        internal
        pure
        returns (uint256[] memory nextArray_)
    {
        if (_itemsToRemove.length == 0) {
            return _self;
        }

        bool[] memory indexesToRemove = new bool[](_self.length);
        uint256 remainingItemsCount = _self.length;
        for (uint256 i; i < _self.length; i++) {
            if (contains(_itemsToRemove, _self[i])) {
                indexesToRemove[i] = true;
                remainingItemsCount--;
            }
        }

        if (remainingItemsCount == _self.length) {
            nextArray_ = _self;
        } else if (remainingItemsCount > 0) {
            nextArray_ = new uint256[](remainingItemsCount);
            uint256 nextArrayIndex;
            for (uint256 i; i < _self.length; i++) {
                if (!indexesToRemove[i]) {
                    nextArray_[nextArrayIndex] = _self[i];
                    nextArrayIndex++;
                }
            }
        }

        return nextArray_;
    }
}

File 8 of 16 : AssetHelpers.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.

    (c) Enzyme Council <[email protected]>

    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity 0.8.19;

import {IERC20} from "../../external-interfaces/IERC20.sol";
import {WrappedSafeERC20 as SafeERC20} from "../../utils/0.8.19/open-zeppelin/WrappedSafeERC20.sol";

/// @title AssetHelpers Contract
/// @author Enzyme Council <[email protected]>
/// @notice A util contract for common token actions
abstract contract AssetHelpers {
    using SafeERC20 for IERC20;

    /// @dev Helper to aggregate amounts of the same assets
    function __aggregateAssetAmounts(address[] memory _rawAssets, uint256[] memory _rawAmounts)
        internal
        pure
        returns (address[] memory aggregatedAssets_, uint256[] memory aggregatedAmounts_)
    {
        if (_rawAssets.length == 0) {
            return (aggregatedAssets_, aggregatedAmounts_);
        }

        uint256 aggregatedAssetCount = 1;
        for (uint256 i = 1; i < _rawAssets.length; i++) {
            bool contains;
            for (uint256 j; j < i; j++) {
                if (_rawAssets[i] == _rawAssets[j]) {
                    contains = true;
                    break;
                }
            }
            if (!contains) {
                aggregatedAssetCount++;
            }
        }

        aggregatedAssets_ = new address[](aggregatedAssetCount);
        aggregatedAmounts_ = new uint256[](aggregatedAssetCount);
        uint256 aggregatedAssetIndex;
        for (uint256 i; i < _rawAssets.length; i++) {
            bool contains;
            for (uint256 j; j < aggregatedAssetIndex; j++) {
                if (_rawAssets[i] == aggregatedAssets_[j]) {
                    contains = true;

                    aggregatedAmounts_[j] += _rawAmounts[i];

                    break;
                }
            }
            if (!contains) {
                aggregatedAssets_[aggregatedAssetIndex] = _rawAssets[i];
                aggregatedAmounts_[aggregatedAssetIndex] = _rawAmounts[i];
                aggregatedAssetIndex++;
            }
        }

        return (aggregatedAssets_, aggregatedAmounts_);
    }

    /// @dev Helper to approve a target account with the max amount of an asset.
    /// This is helpful for fully trusted contracts, such as adapters that
    /// interact with external protocol like Uniswap, Compound, etc.
    function __approveAssetMaxAsNeeded(address _asset, address _target, uint256 _neededAmount) internal {
        uint256 allowance = IERC20(_asset).allowance(address(this), _target);
        if (allowance < _neededAmount) {
            if (allowance > 0) {
                IERC20(_asset).safeApprove(_target, 0);
            }
            IERC20(_asset).safeApprove(_target, type(uint256).max);
        }
    }

    /// @dev Helper to transfer full asset balance from the current contract to a target
    function __pushFullAssetBalance(address _target, address _asset) internal returns (uint256 amountTransferred_) {
        amountTransferred_ = IERC20(_asset).balanceOf(address(this));
        if (amountTransferred_ > 0) {
            IERC20(_asset).safeTransfer(_target, amountTransferred_);
        }

        return amountTransferred_;
    }

    /// @dev Helper to transfer full asset balances from the current contract to a target
    function __pushFullAssetBalances(address _target, address[] memory _assets)
        internal
        returns (uint256[] memory amountsTransferred_)
    {
        amountsTransferred_ = new uint256[](_assets.length);
        for (uint256 i; i < _assets.length; i++) {
            IERC20 assetContract = IERC20(_assets[i]);
            amountsTransferred_[i] = assetContract.balanceOf(address(this));
            if (amountsTransferred_[i] > 0) {
                assetContract.safeTransfer(_target, amountsTransferred_[i]);
            }
        }

        return amountsTransferred_;
    }
}

File 9 of 16 : WrappedSafeERC20.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.

    (c) Enzyme Council <[email protected]>

    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity 0.8.19;

import {IERC20 as OpenZeppelinIERC20} from "openzeppelin-solc-0.8/token/ERC20/IERC20.sol";
import {SafeERC20 as OpenZeppelinSafeERC20} from "openzeppelin-solc-0.8/token/ERC20/utils/SafeERC20.sol";
import {IERC20} from "../../../external-interfaces/IERC20.sol";

/// @title WrappedSafeERC20 Library
/// @author Enzyme Council <[email protected]>
/// @notice Wraps OpenZeppelin's SafeERC20 library to use the local IERC20 interface for inputs
library WrappedSafeERC20 {
    function safeApprove(IERC20 _token, address _spender, uint256 _value) internal {
        OpenZeppelinSafeERC20.safeApprove({token: __castToken(_token), spender: _spender, value: _value});
    }

    function safeDecreaseAllowance(IERC20 _token, address _spender, uint256 _value) internal {
        OpenZeppelinSafeERC20.safeDecreaseAllowance({token: __castToken(_token), spender: _spender, value: _value});
    }

    function safeIncreaseAllowance(IERC20 _token, address _spender, uint256 _value) internal {
        OpenZeppelinSafeERC20.safeIncreaseAllowance({token: __castToken(_token), spender: _spender, value: _value});
    }

    function safeTransfer(IERC20 _token, address _to, uint256 _value) internal {
        OpenZeppelinSafeERC20.safeTransfer({token: __castToken(_token), to: _to, value: _value});
    }

    function safeTransferFrom(IERC20 _token, address _from, address _to, uint256 _value) internal {
        OpenZeppelinSafeERC20.safeTransferFrom({token: __castToken(_token), from: _from, to: _to, value: _value});
    }

    function __castToken(IERC20 _token) private pure returns (OpenZeppelinIERC20 token_) {
        return OpenZeppelinIERC20(address(_token));
    }
}

File 10 of 16 : AlicePositionLibBase1.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.

    (c) Enzyme Foundation <[email protected]>

    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity 0.8.19;

/// @title AlicePositionLibBase1 Contract
/// @author Enzyme Foundation <[email protected]>
/// @notice A persistent contract containing all required storage variables and
/// required functions for a AlicePositionLib implementation
/// @dev DO NOT EDIT CONTRACT. If new events or storage are necessary, they should be added to
/// a numbered AlicePositionLibBaseXXX that inherits the previous base.
/// e.g., `AlicePositionLibBase2 is AlicePositionLibBase1`
abstract contract AlicePositionLibBase1 {
    struct OrderDetails {
        address outgoingAssetAddress;
        address incomingAssetAddress;
        uint256 outgoingAmount;
    }

    event OrderIdAdded(uint256 indexed orderId, OrderDetails orderDetails);

    event OrderIdRemoved(uint256 indexed orderId);

    uint256[] internal orderIds;

    mapping(uint256 orderId => OrderDetails) orderIdToOrderDetails;
}

File 11 of 16 : IAlicePosition.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.
    (c) Enzyme Foundation <[email protected]>
    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

import {IExternalPosition} from "../../IExternalPosition.sol";
import {AlicePositionLibBase1} from "./bases/AlicePositionLibBase1.sol";

pragma solidity >=0.6.0 <0.9.0;

/// @title IAlicePosition Interface
/// @author Enzyme Foundation <[email protected]>
interface IAlicePosition is IExternalPosition {
    enum Actions {
        PlaceOrder,
        RefundOrder,
        Sweep
    }

    struct PlaceOrderActionArgs {
        uint16 instrumentId;
        bool isBuyOrder;
        uint256 quantityToSell;
        uint256 limitAmountToGet;
    }

    struct SweepActionArgs {
        uint256[] orderIds;
    }

    struct RefundOrderActionArgs {
        uint256 orderId;
        uint16 instrumentId;
        bool isBuyOrder;
        uint256 quantityToSell;
        uint256 limitAmountToGet;
        uint256 timestamp;
    }

    function getOrderDetails(uint256 _orderId)
        external
        view
        returns (AlicePositionLibBase1.OrderDetails memory orderDetails_);

    function getOrderIds() external view returns (uint256[] memory orderIds_);
}

File 12 of 16 : IERC20.sol
// 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);
}

File 13 of 16 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.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");
        }
    }
}

File 14 of 16 : IExternalPosition.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.
    (c) Enzyme Council <[email protected]>
    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity >=0.6.0 <0.9.0;

import {IExternalPositionLibCore} from "../../../persistent/external-positions/IExternalPositionLibCore.sol";

/// @title IExternalPosition Contract
/// @author Enzyme Council <[email protected]>
interface IExternalPosition is IExternalPositionLibCore {
    function getDebtAssets() external returns (address[] memory assets_, uint256[] memory amounts_);

    function getManagedAssets() external returns (address[] memory assets_, uint256[] memory amounts_);

    function init(bytes memory _data) external;
}

File 15 of 16 : draft-IERC20Permit.sol
// 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);
}

File 16 of 16 : IExternalPositionLibCore.sol
// SPDX-License-Identifier: GPL-3.0

/*
    This file is part of the Enzyme Protocol.
    (c) Enzyme Council <[email protected]>
    For the full license information, please view the LICENSE
    file that was distributed with this source code.
*/

pragma solidity >=0.6.0 <0.9.0;

/// @title IExternalPositionLibCore interface
/// @author Enzyme Council <[email protected]>
/// @notice An interface for core required functions of an IExternalPositionLib instance
interface IExternalPositionLibCore {
    function receiveCallFromVault(bytes memory _data) external;
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=lib/openzeppelin-solc-0.6/contracts/",
    "@uniswap/v3-core/=lib/uniswap-v3-core/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "morpho-blue/=lib/morpho-blue/src/libraries/",
    "openzeppelin-solc-0.6/=lib/openzeppelin-solc-0.6/contracts/",
    "openzeppelin-solc-0.7/=lib/openzeppelin-solc-0.7/contracts/",
    "openzeppelin-solc-0.8/=lib/openzeppelin-solc-0.8/contracts/",
    "uniswap-v3-core/=lib/uniswap-v3-core/",
    "uniswap-v3-core-0.8/=lib/uniswap-v3-core-0.8/",
    "uniswap-v3-periphery/=lib/uniswap-v3-periphery/contracts/",
    "uniswap-v3-periphery-0.8/=lib/uniswap-v3-periphery-0.8/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200,
    "details": {
      "yul": false
    }
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": false
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_aliceOrderManagerAddress","type":"address"},{"internalType":"address","name":"_wrappedNativeAssetAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidActionId","type":"error"},{"inputs":[],"name":"OrderNotSettledOrCancelled","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"orderId","type":"uint256"},{"components":[{"internalType":"address","name":"outgoingAssetAddress","type":"address"},{"internalType":"address","name":"incomingAssetAddress","type":"address"},{"internalType":"uint256","name":"outgoingAmount","type":"uint256"}],"indexed":false,"internalType":"struct AlicePositionLibBase1.OrderDetails","name":"orderDetails","type":"tuple"}],"name":"OrderIdAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"OrderIdRemoved","type":"event"},{"inputs":[],"name":"getDebtAssets","outputs":[{"internalType":"address[]","name":"assets_","type":"address[]"},{"internalType":"uint256[]","name":"amounts_","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getManagedAssets","outputs":[{"internalType":"address[]","name":"assets_","type":"address[]"},{"internalType":"uint256[]","name":"amounts_","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_orderId","type":"uint256"}],"name":"getOrderDetails","outputs":[{"components":[{"internalType":"address","name":"outgoingAssetAddress","type":"address"},{"internalType":"address","name":"incomingAssetAddress","type":"address"},{"internalType":"uint256","name":"outgoingAmount","type":"uint256"}],"internalType":"struct AlicePositionLibBase1.OrderDetails","name":"orderDetails_","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOrderIds","outputs":[{"internalType":"uint256[]","name":"orderIds_","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_actionData","type":"bytes"}],"name":"receiveCallFromVault","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c06040523480156200001157600080fd5b506040516200219e3803806200219e833981016040819052620000349162000086565b6001600160a01b039182166080521660a052620000c9565b60006001600160a01b0382165b92915050565b6200006a816200004c565b81146200007657600080fd5b50565b805162000059816200005f565b600080604083850312156200009e576200009e600080fd5b6000620000ac858562000079565b9250506020620000bf8582860162000079565b9150509250929050565b60805160a05161208562000119600039600081816101a20152610a8b01526000818161044c015281816109aa01528181610b0d01528181610b5a01528181610cef0152610eab01526120856000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c80634ddf47d41461006757806380daddb81461007a5780639e0acf8f14610099578063e5c23a97146100ae578063ec7dd7bb146100c1578063ecd658b4146100e1575b600080fd5b610078610075366004611643565b50565b005b6100826100e9565b60405161009092919061174b565b60405180910390f35b6100a1610315565b6040516100909190611770565b6100786100bc366004611643565b61036d565b6100d46100cf366004611799565b6103d7565b60405161009091906117f1565b606080610082565b60608060006100f6610315565b9050606060005b82518110156101fa57600061012a84838151811061011d5761011d6117ff565b60200260200101516103d7565b90506000610150858481518110610143576101436117ff565b6020026020010151610432565b905080156101855781516101659085906104d4565b935061017e8260200151856104d490919063ffffffff16565b93506101e5565b81516101c9906001600160a01b0316156101a05782516101c2565b7f00000000000000000000000000000000000000000000000000000000000000005b88906104ff565b96506101e28260400151876105f090919063ffffffff16565b95505b505080806101f29061182b565b9150506100fd565b5060005b815181101561030057600082828151811061021b5761021b6117ff565b602002602001015190506000806001600160a01b0316826001600160a01b0316146102b2576040516370a0823160e01b81526001600160a01b038316906370a082319061026c903090600401611845565b602060405180830381865afa158015610289573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ad919061185e565b6102b4565b475b9050806000036102c55750506102ee565b6102dd6001600160a01b038316156101a057826101c2565b96506102e986826105f0565b955050505b806102f88161182b565b9150506101fe565b5061030b84846106c0565b9350935050509091565b6060600080548060200260200160405190810160405280929190818152602001828054801561036357602002820191906000526020600020905b81548152602001906001019080831161034f575b5050505050905090565b6000808280602001905181019061038491906118fb565b90925090508161039c5761039781610975565b505050565b600282036103ad5761039781610c07565b600182036103be5761039781610cb7565b60405163703469d160e11b815260040160405180910390fd5b6040805160608082018352600080835260208084018290529284018190529384526001808352938390208351918201845280546001600160a01b03908116835294810154909416918101919091526002909201549082015290565b604051635cf86b4760e11b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b9f0d68e90610481908590600401611953565b602060405180830381865afa9250505080156104ba575060408051601f3d908101601f191682019092526104b79181019061185e565b60015b6104c657506001919050565b50600092915050565b919050565b60606104e08383610e37565b156104ec5750816104f9565b6104f683836104ff565b90505b92915050565b60608251600161050f9190611961565b67ffffffffffffffff8111156105275761052761154d565b604051908082528060200260200182016040528015610550578160200160208202803683370190505b50905060005b83518110156105b557838181518110610571576105716117ff565b602002602001015182828151811061058b5761058b6117ff565b6001600160a01b0390921660209283029190910190910152806105ad8161182b565b915050610556565b5081818451815181106105ca576105ca6117ff565b60200260200101906001600160a01b031690816001600160a01b03168152505092915050565b6060825160016106009190611961565b67ffffffffffffffff8111156106185761061861154d565b604051908082528060200260200182016040528015610641578160200160208202803683370190505b50905060005b835181101561069957838181518110610662576106626117ff565b602002602001015182828151811061067c5761067c6117ff565b6020908102919091010152806106918161182b565b915050610647565b5081818451815181106106ae576106ae6117ff565b60200260200101818152505092915050565b60608083516000031561096e576001805b8551811015610773576000805b8281101561074c578781815181106106f8576106f86117ff565b60200260200101516001600160a01b031688848151811061071b5761071b6117ff565b60200260200101516001600160a01b03160361073a576001915061074c565b806107448161182b565b9150506106de565b5080610760578261075c8161182b565b9350505b508061076b8161182b565b9150506106d1565b508067ffffffffffffffff81111561078d5761078d61154d565b6040519080825280602002602001820160405280156107b6578160200160208202803683370190505b5092508067ffffffffffffffff8111156107d2576107d261154d565b6040519080825280602002602001820160405280156107fb578160200160208202803683370190505b5091506000805b865181101561096a576000805b838110156108c057868181518110610829576108296117ff565b60200260200101516001600160a01b031689848151811061084c5761084c6117ff565b60200260200101516001600160a01b0316036108ae5760019150878381518110610878576108786117ff565b6020026020010151868281518110610892576108926117ff565b602002602001018181516108a69190611961565b9052506108c0565b806108b88161182b565b91505061080f565b5080610957578782815181106108d8576108d86117ff565b60200260200101518684815181106108f2576108f26117ff565b60200260200101906001600160a01b031690816001600160a01b031681525050868281518110610924576109246117ff565b602002602001015185848151811061093e5761093e6117ff565b6020908102919091010152826109538161182b565b9350505b50806109628161182b565b915050610802565b5050505b9250929050565b60008180602001905181019061098b9190611a0e565b80516040516310da0a2360e11b81529192506000916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916321b41446916109e19190600190600401611a41565b608060405180830381865afa1580156109fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a229190611ad6565b905060008260200151610a39578160400151610a3f565b81606001515b905060008360200151610a56578260600151610a5c565b82604001515b905060006001600160a01b038316610af757506040808501519051632e1a7d4d60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90610ac0908490600401611953565b600060405180830381600087803b158015610ada57600080fd5b505af1158015610aee573d6000803e3d6000fd5b50505050610b32565b6040850151610b32906001600160a01b038516907f000000000000000000000000000000000000000000000000000000000000000090610e9c565b84516020860151604080880151606089015191516311f5d2a960e31b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001694638fae9548948794610b94949293919291600401611af7565b6000604051808303818588803b158015610bad57600080fd5b505af1158015610bc1573d6000803e3d6000fd5b5050505050610bff6040518060600160405280856001600160a01b03168152602001846001600160a01b031681526020018760400151815250610ea7565b505050505050565b600081806020019051810190610c1d9190611c29565b905060005b81515181101561039757600082600001518281518110610c4457610c446117ff565b60200260200101519050610c5781610432565b610c74576040516301870ddf60e71b815260040160405180910390fd5b6000610c7f826103d7565b9050610c8a82610fe6565b610c97816020015161104f565b8051610ca29061104f565b50508080610caf9061182b565b915050610c22565b600081806020019051810190610ccd9190611cfe565b90506000610cde82600001516103d7565b9050610ced8260000151610fe6565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f2d7899283600001513085602001518660400151876060015188608001518960a001516040518863ffffffff1660e01b8152600401610d5d9796959493929190611d1f565b600060405180830381600087803b158015610d7757600080fd5b505af1158015610d8b573d6000803e3d6000fd5b505082519150506001600160a01b038116610daf57610daa334761110c565b610e31565b610e3133826001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610ddf9190611845565b602060405180830381865afa158015610dfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e20919061185e565b6001600160a01b03841691906111b1565b50505050565b6000805b8351811015610e9257838181518110610e5657610e566117ff565b60200260200101516001600160a01b0316836001600160a01b031603610e805760019150506104f9565b80610e8a8161182b565b915050610e3b565b5060009392505050565b6103978383836111bc565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b251d6056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2b919061185e565b60008054600180820183557f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5639091018390558282526020818152604092839020865181546001600160a01b03199081166001600160a01b039283161783559288015193820180549093169316929092179055848201516002909101555190915081907fd9eeae417ff406e218312809f653d23ef0c3a029d2e9c3a1792c010fd35399ef90610fda9085906117f1565b60405180910390a25050565b610ff16000826112a7565b50600081815260016020819052604080832080546001600160a01b03199081168255928101805490931690925560029091018290555182917fd00f9df87317e48136dba4680c6b7e5a9763552f7c9fe645f8e992f22231437a91a250565b60006001600160a01b038216156110d2576040516370a0823160e01b81526001600160a01b038316906370a082319061108c903090600401611845565b602060405180830381865afa1580156110a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110cd919061185e565b6110d4565b475b905080156110f4576001600160a01b0382166110f8576110f4338261110c565b5050565b6110f46001600160a01b03831633836111b1565b804710156111355760405162461bcd60e51b815260040161112c90611dbe565b60405180910390fd5b6000826001600160a01b03168260405161114e90611dce565b60006040518083038185875af1925050503d806000811461118b576040519150601f19603f3d011682016040523d82523d6000602084013e611190565b606091505b50509050806103975760405162461bcd60e51b815260040161112c90611e33565b61039783838361137a565b8015806112355750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906111f29030908690600401611e43565b602060405180830381865afa15801561120f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611233919061185e565b155b6112515760405162461bcd60e51b815260040161112c90611eb1565b6103978363095ea7b360e01b8484604051602401611270929190611ec1565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611399565b8154600090815b8181101561137257838582815481106112c9576112c96117ff565b906000526020600020015403611360576112e4600183611edc565b81101561133157846112f7600184611edc565b81548110611307576113076117ff565b9060005260206000200154858281548110611324576113246117ff565b6000918252602090912001555b8480548061134157611341611eef565b6001900381819060005260206000200160009055905560019250611372565b8061136a8161182b565b9150506112ae565b505092915050565b6103978363a9059cbb60e01b8484604051602401611270929190611ec1565b60006113ee826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166114289092919063ffffffff16565b805190915015610397578080602001905181019061140c9190611f05565b6103975760405162461bcd60e51b815260040161112c90611f6d565b60606114378484600085611441565b90505b9392505050565b6060824710156114635760405162461bcd60e51b815260040161112c90611fc0565b600080866001600160a01b0316858760405161147f9190611ff2565b60006040518083038185875af1925050503d80600081146114bc576040519150601f19603f3d011682016040523d82523d6000602084013e6114c1565b606091505b50915091506114d2878383876114df565b925050505b949350505050565b6060831561151e578251600003611517576001600160a01b0385163b6115175760405162461bcd60e51b815260040161112c90612032565b50816114d7565b6114d783838151156115335781518083602001fd5b8060405162461bcd60e51b815260040161112c9190612074565b634e487b7160e01b600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff821117156115895761158961154d565b6040525050565b600061159b60405190565b90506104cf8282611563565b600067ffffffffffffffff8211156115c1576115c161154d565b601f19601f83011660200192915050565b82818337506000910152565b60006115f16115ec846115a7565b611590565b90508281526020810184848401111561160c5761160c600080fd5b6116178482856115d2565b509392505050565b600082601f83011261163357611633600080fd5b81356114d78482602086016115de565b60006020828403121561165857611658600080fd5b813567ffffffffffffffff81111561167257611672600080fd5b6114d78482850161161f565b60006001600160a01b0382166104f9565b6116988161167e565b82525050565b60006116aa838361168f565b505060200190565b60006116bc825190565b80845260209384019383018060005b838110156116f05781516116df888261169e565b9750602083019250506001016116cb565b509495945050505050565b80611698565b60006116aa83836116fb565b6000611717825190565b80845260209384019383018060005b838110156116f057815161173a8882611701565b975060208301925050600101611726565b6040808252810161175c81856116b2565b90508181036020830152611437818461170d565b602080825281016104f6818461170d565b805b811461007557600080fd5b80356104f981611781565b6000602082840312156117ae576117ae600080fd5b60006114d7848461178e565b805160608301906117cb848261168f565b5060208201516117de602085018261168f565b506040820151610e3160408501826116fb565b606081016104f982846117ba565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019820361183e5761183e611815565b5060010190565b602081016104f9828461168f565b80516104f981611781565b60006020828403121561187357611873600080fd5b60006114d78484611853565b60005b8381101561189a578181015183820152602001611882565b50506000910152565b60006118b16115ec846115a7565b9050828152602081018484840111156118cc576118cc600080fd5b61161784828561187f565b600082601f8301126118eb576118eb600080fd5b81516114d78482602086016118a3565b6000806040838503121561191157611911600080fd5b600061191d8585611853565b925050602083015167ffffffffffffffff81111561193d5761193d600080fd5b611949858286016118d7565b9150509250929050565b602081016104f982846116fb565b808201808211156104f9576104f9611815565b61ffff8116611783565b80516104f981611974565b801515611783565b80516104f981611989565b6000608082840312156119b1576119b1600080fd5b6119bb6080611590565b905060006119c9848461197e565b82525060206119da84848301611991565b60208301525060406119ee84828501611853565b6040830152506060611a0284828501611853565b60608301525092915050565b600060808284031215611a2357611a23600080fd5b60006114d7848461199c565b61ffff8116611698565b801515611698565b60408101611a4f8285611a2f565b61143a6020830184611a39565b6117838161167e565b80516104f981611a5c565b600060808284031215611a8557611a85600080fd5b611a8f6080611590565b90506000611a9d848461197e565b8252506020611aae84848301611991565b6020830152506040611ac284828501611a65565b6040830152506060611a0284828501611a65565b600060808284031215611aeb57611aeb600080fd5b60006114d78484611a70565b60808101611b058287611a2f565b611b126020830186611a39565b611b1f60408301856116fb565b611b2c60608301846116fb565b95945050505050565b600067ffffffffffffffff821115611b4f57611b4f61154d565b5060209081020190565b6000611b676115ec84611b35565b83815290506020808201908402830185811115611b8657611b86600080fd5b835b81811015611baa5780611b9b8882611853565b84525060209283019201611b88565b5050509392505050565b600082601f830112611bc857611bc8600080fd5b81516114d7848260208601611b59565b600060208284031215611bed57611bed600080fd5b611bf76020611590565b825190915067ffffffffffffffff811115611c1457611c14600080fd5b611c2084828501611bb4565b82525092915050565b600060208284031215611c3e57611c3e600080fd5b815167ffffffffffffffff811115611c5857611c58600080fd5b6114d784828501611bd8565b600060c08284031215611c7957611c79600080fd5b611c8360c0611590565b90506000611c918484611853565b8252506020611ca28484830161197e565b6020830152506040611cb684828501611991565b6040830152506060611cca84828501611853565b6060830152506080611cde84828501611853565b60808301525060a0611cf284828501611853565b60a08301525092915050565b600060c08284031215611d1357611d13600080fd5b60006114d78484611c64565b60e08101611d2d828a6116fb565b611d3a602083018961168f565b611d476040830188611a2f565b611d546060830187611a39565b611d6160808301866116fb565b611d6e60a08301856116fb565b611d7b60c08301846116fb565b98975050505050505050565b601d81526000602082017f416464726573733a20696e73756666696369656e742062616c616e6365000000815291505b5060200190565b602080825281016104f981611d87565b6000816104f9565b603a81526000602082017f416464726573733a20756e61626c6520746f2073656e642076616c75652c207281527f6563697069656e74206d61792068617665207265766572746564000000000000602082015291505b5060400190565b602080825281016104f981611dd6565b60408101611e51828561168f565b61143a602083018461168f565b603681526000602082017f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f81527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60208201529150611e2c565b602080825281016104f981611e5e565b60408101611ecf828561168f565b61143a60208301846116fb565b818103818111156104f9576104f9611815565b634e487b7160e01b600052603160045260246000fd5b600060208284031215611f1a57611f1a600080fd5b60006114d78484611991565b602a81526000602082017f5361666545524332303a204552433230206f7065726174696f6e20646964206e8152691bdd081cdd58d8d9595960b21b60208201529150611e2c565b602080825281016104f981611f26565b602681526000602082017f416464726573733a20696e73756666696369656e742062616c616e636520666f8152651c8818d85b1b60d21b60208201529150611e2c565b602080825281016104f981611f7d565b6000611fda825190565b611fe881856020860161187f565b9290920192915050565b600061143a8284611fd0565b601d81526000602082017f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081529150611db7565b602080825281016104f981611ffe565b600061204c825190565b80845260208401935061206381856020860161187f565b601f01601f19169290920192915050565b602080825281016104f6818461204256000000000000000000000000841473a19279e54a850e9083a3a57de9e6244d2e000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100625760003560e01c80634ddf47d41461006757806380daddb81461007a5780639e0acf8f14610099578063e5c23a97146100ae578063ec7dd7bb146100c1578063ecd658b4146100e1575b600080fd5b610078610075366004611643565b50565b005b6100826100e9565b60405161009092919061174b565b60405180910390f35b6100a1610315565b6040516100909190611770565b6100786100bc366004611643565b61036d565b6100d46100cf366004611799565b6103d7565b60405161009091906117f1565b606080610082565b60608060006100f6610315565b9050606060005b82518110156101fa57600061012a84838151811061011d5761011d6117ff565b60200260200101516103d7565b90506000610150858481518110610143576101436117ff565b6020026020010151610432565b905080156101855781516101659085906104d4565b935061017e8260200151856104d490919063ffffffff16565b93506101e5565b81516101c9906001600160a01b0316156101a05782516101c2565b7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25b88906104ff565b96506101e28260400151876105f090919063ffffffff16565b95505b505080806101f29061182b565b9150506100fd565b5060005b815181101561030057600082828151811061021b5761021b6117ff565b602002602001015190506000806001600160a01b0316826001600160a01b0316146102b2576040516370a0823160e01b81526001600160a01b038316906370a082319061026c903090600401611845565b602060405180830381865afa158015610289573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ad919061185e565b6102b4565b475b9050806000036102c55750506102ee565b6102dd6001600160a01b038316156101a057826101c2565b96506102e986826105f0565b955050505b806102f88161182b565b9150506101fe565b5061030b84846106c0565b9350935050509091565b6060600080548060200260200160405190810160405280929190818152602001828054801561036357602002820191906000526020600020905b81548152602001906001019080831161034f575b5050505050905090565b6000808280602001905181019061038491906118fb565b90925090508161039c5761039781610975565b505050565b600282036103ad5761039781610c07565b600182036103be5761039781610cb7565b60405163703469d160e11b815260040160405180910390fd5b6040805160608082018352600080835260208084018290529284018190529384526001808352938390208351918201845280546001600160a01b03908116835294810154909416918101919091526002909201549082015290565b604051635cf86b4760e11b81526000906001600160a01b037f000000000000000000000000841473a19279e54a850e9083a3a57de9e6244d2e169063b9f0d68e90610481908590600401611953565b602060405180830381865afa9250505080156104ba575060408051601f3d908101601f191682019092526104b79181019061185e565b60015b6104c657506001919050565b50600092915050565b919050565b60606104e08383610e37565b156104ec5750816104f9565b6104f683836104ff565b90505b92915050565b60608251600161050f9190611961565b67ffffffffffffffff8111156105275761052761154d565b604051908082528060200260200182016040528015610550578160200160208202803683370190505b50905060005b83518110156105b557838181518110610571576105716117ff565b602002602001015182828151811061058b5761058b6117ff565b6001600160a01b0390921660209283029190910190910152806105ad8161182b565b915050610556565b5081818451815181106105ca576105ca6117ff565b60200260200101906001600160a01b031690816001600160a01b03168152505092915050565b6060825160016106009190611961565b67ffffffffffffffff8111156106185761061861154d565b604051908082528060200260200182016040528015610641578160200160208202803683370190505b50905060005b835181101561069957838181518110610662576106626117ff565b602002602001015182828151811061067c5761067c6117ff565b6020908102919091010152806106918161182b565b915050610647565b5081818451815181106106ae576106ae6117ff565b60200260200101818152505092915050565b60608083516000031561096e576001805b8551811015610773576000805b8281101561074c578781815181106106f8576106f86117ff565b60200260200101516001600160a01b031688848151811061071b5761071b6117ff565b60200260200101516001600160a01b03160361073a576001915061074c565b806107448161182b565b9150506106de565b5080610760578261075c8161182b565b9350505b508061076b8161182b565b9150506106d1565b508067ffffffffffffffff81111561078d5761078d61154d565b6040519080825280602002602001820160405280156107b6578160200160208202803683370190505b5092508067ffffffffffffffff8111156107d2576107d261154d565b6040519080825280602002602001820160405280156107fb578160200160208202803683370190505b5091506000805b865181101561096a576000805b838110156108c057868181518110610829576108296117ff565b60200260200101516001600160a01b031689848151811061084c5761084c6117ff565b60200260200101516001600160a01b0316036108ae5760019150878381518110610878576108786117ff565b6020026020010151868281518110610892576108926117ff565b602002602001018181516108a69190611961565b9052506108c0565b806108b88161182b565b91505061080f565b5080610957578782815181106108d8576108d86117ff565b60200260200101518684815181106108f2576108f26117ff565b60200260200101906001600160a01b031690816001600160a01b031681525050868281518110610924576109246117ff565b602002602001015185848151811061093e5761093e6117ff565b6020908102919091010152826109538161182b565b9350505b50806109628161182b565b915050610802565b5050505b9250929050565b60008180602001905181019061098b9190611a0e565b80516040516310da0a2360e11b81529192506000916001600160a01b037f000000000000000000000000841473a19279e54a850e9083a3a57de9e6244d2e16916321b41446916109e19190600190600401611a41565b608060405180830381865afa1580156109fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a229190611ad6565b905060008260200151610a39578160400151610a3f565b81606001515b905060008360200151610a56578260600151610a5c565b82604001515b905060006001600160a01b038316610af757506040808501519051632e1a7d4d60e01b81526001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21690632e1a7d4d90610ac0908490600401611953565b600060405180830381600087803b158015610ada57600080fd5b505af1158015610aee573d6000803e3d6000fd5b50505050610b32565b6040850151610b32906001600160a01b038516907f000000000000000000000000841473a19279e54a850e9083a3a57de9e6244d2e90610e9c565b84516020860151604080880151606089015191516311f5d2a960e31b81526001600160a01b037f000000000000000000000000841473a19279e54a850e9083a3a57de9e6244d2e1694638fae9548948794610b94949293919291600401611af7565b6000604051808303818588803b158015610bad57600080fd5b505af1158015610bc1573d6000803e3d6000fd5b5050505050610bff6040518060600160405280856001600160a01b03168152602001846001600160a01b031681526020018760400151815250610ea7565b505050505050565b600081806020019051810190610c1d9190611c29565b905060005b81515181101561039757600082600001518281518110610c4457610c446117ff565b60200260200101519050610c5781610432565b610c74576040516301870ddf60e71b815260040160405180910390fd5b6000610c7f826103d7565b9050610c8a82610fe6565b610c97816020015161104f565b8051610ca29061104f565b50508080610caf9061182b565b915050610c22565b600081806020019051810190610ccd9190611cfe565b90506000610cde82600001516103d7565b9050610ced8260000151610fe6565b7f000000000000000000000000841473a19279e54a850e9083a3a57de9e6244d2e6001600160a01b031663f2d7899283600001513085602001518660400151876060015188608001518960a001516040518863ffffffff1660e01b8152600401610d5d9796959493929190611d1f565b600060405180830381600087803b158015610d7757600080fd5b505af1158015610d8b573d6000803e3d6000fd5b505082519150506001600160a01b038116610daf57610daa334761110c565b610e31565b610e3133826001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610ddf9190611845565b602060405180830381865afa158015610dfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e20919061185e565b6001600160a01b03841691906111b1565b50505050565b6000805b8351811015610e9257838181518110610e5657610e566117ff565b60200260200101516001600160a01b0316836001600160a01b031603610e805760019150506104f9565b80610e8a8161182b565b915050610e3b565b5060009392505050565b6103978383836111bc565b60007f000000000000000000000000841473a19279e54a850e9083a3a57de9e6244d2e6001600160a01b031663b251d6056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2b919061185e565b60008054600180820183557f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5639091018390558282526020818152604092839020865181546001600160a01b03199081166001600160a01b039283161783559288015193820180549093169316929092179055848201516002909101555190915081907fd9eeae417ff406e218312809f653d23ef0c3a029d2e9c3a1792c010fd35399ef90610fda9085906117f1565b60405180910390a25050565b610ff16000826112a7565b50600081815260016020819052604080832080546001600160a01b03199081168255928101805490931690925560029091018290555182917fd00f9df87317e48136dba4680c6b7e5a9763552f7c9fe645f8e992f22231437a91a250565b60006001600160a01b038216156110d2576040516370a0823160e01b81526001600160a01b038316906370a082319061108c903090600401611845565b602060405180830381865afa1580156110a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110cd919061185e565b6110d4565b475b905080156110f4576001600160a01b0382166110f8576110f4338261110c565b5050565b6110f46001600160a01b03831633836111b1565b804710156111355760405162461bcd60e51b815260040161112c90611dbe565b60405180910390fd5b6000826001600160a01b03168260405161114e90611dce565b60006040518083038185875af1925050503d806000811461118b576040519150601f19603f3d011682016040523d82523d6000602084013e611190565b606091505b50509050806103975760405162461bcd60e51b815260040161112c90611e33565b61039783838361137a565b8015806112355750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906111f29030908690600401611e43565b602060405180830381865afa15801561120f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611233919061185e565b155b6112515760405162461bcd60e51b815260040161112c90611eb1565b6103978363095ea7b360e01b8484604051602401611270929190611ec1565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611399565b8154600090815b8181101561137257838582815481106112c9576112c96117ff565b906000526020600020015403611360576112e4600183611edc565b81101561133157846112f7600184611edc565b81548110611307576113076117ff565b9060005260206000200154858281548110611324576113246117ff565b6000918252602090912001555b8480548061134157611341611eef565b6001900381819060005260206000200160009055905560019250611372565b8061136a8161182b565b9150506112ae565b505092915050565b6103978363a9059cbb60e01b8484604051602401611270929190611ec1565b60006113ee826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166114289092919063ffffffff16565b805190915015610397578080602001905181019061140c9190611f05565b6103975760405162461bcd60e51b815260040161112c90611f6d565b60606114378484600085611441565b90505b9392505050565b6060824710156114635760405162461bcd60e51b815260040161112c90611fc0565b600080866001600160a01b0316858760405161147f9190611ff2565b60006040518083038185875af1925050503d80600081146114bc576040519150601f19603f3d011682016040523d82523d6000602084013e6114c1565b606091505b50915091506114d2878383876114df565b925050505b949350505050565b6060831561151e578251600003611517576001600160a01b0385163b6115175760405162461bcd60e51b815260040161112c90612032565b50816114d7565b6114d783838151156115335781518083602001fd5b8060405162461bcd60e51b815260040161112c9190612074565b634e487b7160e01b600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff821117156115895761158961154d565b6040525050565b600061159b60405190565b90506104cf8282611563565b600067ffffffffffffffff8211156115c1576115c161154d565b601f19601f83011660200192915050565b82818337506000910152565b60006115f16115ec846115a7565b611590565b90508281526020810184848401111561160c5761160c600080fd5b6116178482856115d2565b509392505050565b600082601f83011261163357611633600080fd5b81356114d78482602086016115de565b60006020828403121561165857611658600080fd5b813567ffffffffffffffff81111561167257611672600080fd5b6114d78482850161161f565b60006001600160a01b0382166104f9565b6116988161167e565b82525050565b60006116aa838361168f565b505060200190565b60006116bc825190565b80845260209384019383018060005b838110156116f05781516116df888261169e565b9750602083019250506001016116cb565b509495945050505050565b80611698565b60006116aa83836116fb565b6000611717825190565b80845260209384019383018060005b838110156116f057815161173a8882611701565b975060208301925050600101611726565b6040808252810161175c81856116b2565b90508181036020830152611437818461170d565b602080825281016104f6818461170d565b805b811461007557600080fd5b80356104f981611781565b6000602082840312156117ae576117ae600080fd5b60006114d7848461178e565b805160608301906117cb848261168f565b5060208201516117de602085018261168f565b506040820151610e3160408501826116fb565b606081016104f982846117ba565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019820361183e5761183e611815565b5060010190565b602081016104f9828461168f565b80516104f981611781565b60006020828403121561187357611873600080fd5b60006114d78484611853565b60005b8381101561189a578181015183820152602001611882565b50506000910152565b60006118b16115ec846115a7565b9050828152602081018484840111156118cc576118cc600080fd5b61161784828561187f565b600082601f8301126118eb576118eb600080fd5b81516114d78482602086016118a3565b6000806040838503121561191157611911600080fd5b600061191d8585611853565b925050602083015167ffffffffffffffff81111561193d5761193d600080fd5b611949858286016118d7565b9150509250929050565b602081016104f982846116fb565b808201808211156104f9576104f9611815565b61ffff8116611783565b80516104f981611974565b801515611783565b80516104f981611989565b6000608082840312156119b1576119b1600080fd5b6119bb6080611590565b905060006119c9848461197e565b82525060206119da84848301611991565b60208301525060406119ee84828501611853565b6040830152506060611a0284828501611853565b60608301525092915050565b600060808284031215611a2357611a23600080fd5b60006114d7848461199c565b61ffff8116611698565b801515611698565b60408101611a4f8285611a2f565b61143a6020830184611a39565b6117838161167e565b80516104f981611a5c565b600060808284031215611a8557611a85600080fd5b611a8f6080611590565b90506000611a9d848461197e565b8252506020611aae84848301611991565b6020830152506040611ac284828501611a65565b6040830152506060611a0284828501611a65565b600060808284031215611aeb57611aeb600080fd5b60006114d78484611a70565b60808101611b058287611a2f565b611b126020830186611a39565b611b1f60408301856116fb565b611b2c60608301846116fb565b95945050505050565b600067ffffffffffffffff821115611b4f57611b4f61154d565b5060209081020190565b6000611b676115ec84611b35565b83815290506020808201908402830185811115611b8657611b86600080fd5b835b81811015611baa5780611b9b8882611853565b84525060209283019201611b88565b5050509392505050565b600082601f830112611bc857611bc8600080fd5b81516114d7848260208601611b59565b600060208284031215611bed57611bed600080fd5b611bf76020611590565b825190915067ffffffffffffffff811115611c1457611c14600080fd5b611c2084828501611bb4565b82525092915050565b600060208284031215611c3e57611c3e600080fd5b815167ffffffffffffffff811115611c5857611c58600080fd5b6114d784828501611bd8565b600060c08284031215611c7957611c79600080fd5b611c8360c0611590565b90506000611c918484611853565b8252506020611ca28484830161197e565b6020830152506040611cb684828501611991565b6040830152506060611cca84828501611853565b6060830152506080611cde84828501611853565b60808301525060a0611cf284828501611853565b60a08301525092915050565b600060c08284031215611d1357611d13600080fd5b60006114d78484611c64565b60e08101611d2d828a6116fb565b611d3a602083018961168f565b611d476040830188611a2f565b611d546060830187611a39565b611d6160808301866116fb565b611d6e60a08301856116fb565b611d7b60c08301846116fb565b98975050505050505050565b601d81526000602082017f416464726573733a20696e73756666696369656e742062616c616e6365000000815291505b5060200190565b602080825281016104f981611d87565b6000816104f9565b603a81526000602082017f416464726573733a20756e61626c6520746f2073656e642076616c75652c207281527f6563697069656e74206d61792068617665207265766572746564000000000000602082015291505b5060400190565b602080825281016104f981611dd6565b60408101611e51828561168f565b61143a602083018461168f565b603681526000602082017f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f81527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60208201529150611e2c565b602080825281016104f981611e5e565b60408101611ecf828561168f565b61143a60208301846116fb565b818103818111156104f9576104f9611815565b634e487b7160e01b600052603160045260246000fd5b600060208284031215611f1a57611f1a600080fd5b60006114d78484611991565b602a81526000602082017f5361666545524332303a204552433230206f7065726174696f6e20646964206e8152691bdd081cdd58d8d9595960b21b60208201529150611e2c565b602080825281016104f981611f26565b602681526000602082017f416464726573733a20696e73756666696369656e742062616c616e636520666f8152651c8818d85b1b60d21b60208201529150611e2c565b602080825281016104f981611f7d565b6000611fda825190565b611fe881856020860161187f565b9290920192915050565b600061143a8284611fd0565b601d81526000602082017f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081529150611db7565b602080825281016104f981611ffe565b600061204c825190565b80845260208401935061206381856020860161187f565b601f01601f19169290920192915050565b602080825281016104f6818461204256

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000841473a19279e54a850e9083a3a57de9e6244d2e000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2

-----Decoded View---------------
Arg [0] : _aliceOrderManagerAddress (address): 0x841473a19279E54a850E9083A3A57dE9e6244d2E
Arg [1] : _wrappedNativeAssetAddress (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000841473a19279e54a850e9083a3a57de9e6244d2e
Arg [1] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ 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.