xDAI Price: $0.99996 (-0.01%)
Gas: 1 GWei

Contract

0xC92E8bdf79f0507f65a392b0ab4667716BFE0110
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction and 2 Token Transfers found.

Latest 1 internal transaction

Parent Transaction Hash Block From To
164651002021-06-08 10:15:251414 days ago1623147325  Contract Creation0 xDAI
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
GPv2VaultRelayer

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
default evmVersion
File 1 of 6 : GPv2VaultRelayer.sol
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.7.6;
pragma abicoder v2;

import "./interfaces/IERC20.sol";
import "./interfaces/IVault.sol";
import "./libraries/GPv2Transfer.sol";

/// @title Gnosis Protocol v2 Vault Relayer Contract
/// @author Gnosis Developers
contract GPv2VaultRelayer {
    using GPv2Transfer for IVault;

    /// @dev The creator of the contract which has special permissions. This
    /// value is set at creation time and cannot change.
    address private immutable creator;

    /// @dev The vault this relayer is for.
    IVault private immutable vault;

    constructor(IVault vault_) {
        creator = msg.sender;
        vault = vault_;
    }

    /// @dev Modifier that ensures that a function can only be called by the
    /// creator of this contract.
    modifier onlyCreator() {
        require(msg.sender == creator, "GPv2: not creator");
        _;
    }

    /// @dev Transfers all sell amounts for the executed trades from their
    /// owners to the caller.
    ///
    /// This function reverts if:
    /// - The caller is not the creator of the vault relayer
    /// - Any ERC20 transfer fails
    ///
    /// @param transfers The transfers to execute.
    function transferFromAccounts(
        GPv2Transfer.Data[] calldata transfers
    ) external onlyCreator {
        vault.transferFromAccounts(transfers, msg.sender);
    }

    /// @dev Performs a Balancer batched swap on behalf of a user and sends a
    /// fee to the caller.
    ///
    /// This function reverts if:
    /// - The caller is not the creator of the vault relayer
    /// - The swap fails
    /// - The fee transfer fails
    ///
    /// @param kind The Balancer swap kind, this can either be `GIVEN_IN` for
    /// sell orders or `GIVEN_OUT` for buy orders.
    /// @param swaps The swaps to perform.
    /// @param tokens The tokens for the swaps. Swaps encode to and from tokens
    /// as indices into this array.
    /// @param funds The fund management settings, specifying the user the swap
    /// is being performed for as well as the recipient of the proceeds.
    /// @param limits Swap limits for encoding limit prices.
    /// @param deadline The deadline for the swap.
    /// @param feeTransfer The transfer data for the caller fee.
    /// @return tokenDeltas The executed swap amounts.
    function batchSwapWithFee(
        IVault.SwapKind kind,
        IVault.BatchSwapStep[] calldata swaps,
        IERC20[] memory tokens,
        IVault.FundManagement memory funds,
        int256[] memory limits,
        uint256 deadline,
        GPv2Transfer.Data calldata feeTransfer
    ) external onlyCreator returns (int256[] memory tokenDeltas) {
        tokenDeltas = vault.batchSwap(
            kind,
            swaps,
            tokens,
            funds,
            limits,
            deadline
        );
        vault.fastTransferFromAccount(feeTransfer, msg.sender);
    }
}

File 2 of 6 : IERC20.sol
// SPDX-License-Identifier: MIT

// Vendored from OpenZeppelin contracts with minor modifications:
// - Modified Solidity version
// - Formatted code
// - Added `name`, `symbol` and `decimals` function declarations
// <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/token/ERC20/IERC20.sol>

pragma solidity ^0.7.6;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the number of decimals the token uses.
     */
    function decimals() external view returns (uint8);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(
        address owner,
        address spender
    ) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev 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
    );
}

File 3 of 6 : IVault.sol
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity ^0.7.6;
pragma abicoder v2;

import "./IERC20.sol";

/**
 * @dev Minimal interface for the Vault core contract only containing methods
 * used by Gnosis Protocol V2. Original source:
 * <https://github.com/balancer-labs/balancer-core-v2/blob/v1.0.0/contracts/vault/interfaces/IVault.sol>
 */
interface IVault {
    // Internal Balance
    //
    // Users can deposit tokens into the Vault, where they are allocated to their Internal Balance, and later
    // transferred or withdrawn. It can also be used as a source of tokens when joining Pools, as a destination
    // when exiting them, and as either when performing swaps. This usage of Internal Balance results in greatly reduced
    // gas costs when compared to relying on plain ERC20 transfers, leading to large savings for frequent users.
    //
    // Internal Balance management features batching, which means a single contract call can be used to perform multiple
    // operations of different kinds, with different senders and recipients, at once.

    /**
     * @dev Performs a set of user balance operations, which involve Internal Balance (deposit, withdraw or transfer)
     * and plain ERC20 transfers using the Vault's allowance. This last feature is particularly useful for relayers, as
     * it lets integrators reuse a user's Vault allowance.
     *
     * For each operation, if the caller is not `sender`, it must be an authorized relayer for them.
     */
    function manageUserBalance(UserBalanceOp[] memory ops) external payable;

    /**
     * @dev Data for `manageUserBalance` operations, which include the possibility for ETH to be sent and received
     without manual WETH wrapping or unwrapping.
     */
    struct UserBalanceOp {
        UserBalanceOpKind kind;
        IERC20 asset;
        uint256 amount;
        address sender;
        address payable recipient;
    }

    // There are four possible operations in `manageUserBalance`:
    //
    // - DEPOSIT_INTERNAL
    // Increases the Internal Balance of the `recipient` account by transferring tokens from the corresponding
    // `sender`. The sender must have allowed the Vault to use their tokens via `IERC20.approve()`.
    //
    // ETH can be used by passing the ETH sentinel value as the asset and forwarding ETH in the call: it will be wrapped
    // and deposited as WETH. Any ETH amount remaining will be sent back to the caller (not the sender, which is
    // relevant for relayers).
    //
    // Emits an `InternalBalanceChanged` event.
    //
    //
    // - WITHDRAW_INTERNAL
    // Decreases the Internal Balance of the `sender` account by transferring tokens to the `recipient`.
    //
    // ETH can be used by passing the ETH sentinel value as the asset. This will deduct WETH instead, unwrap it and send
    // it to the recipient as ETH.
    //
    // Emits an `InternalBalanceChanged` event.
    //
    //
    // - TRANSFER_INTERNAL
    // Transfers tokens from the Internal Balance of the `sender` account to the Internal Balance of `recipient`.
    //
    // Reverts if the ETH sentinel value is passed.
    //
    // Emits an `InternalBalanceChanged` event.
    //
    //
    // - TRANSFER_EXTERNAL
    // Transfers tokens from `sender` to `recipient`, using the Vault's ERC20 allowance. This is typically used by
    // relayers, as it lets them reuse a user's Vault allowance.
    //
    // Reverts if the ETH sentinel value is passed.
    //
    // Emits an `ExternalBalanceTransfer` event.

    enum UserBalanceOpKind {
        DEPOSIT_INTERNAL,
        WITHDRAW_INTERNAL,
        TRANSFER_INTERNAL,
        TRANSFER_EXTERNAL
    }

    // Swaps
    //
    // Users can swap tokens with Pools by calling the `swap` and `batchSwap` functions. To do this,
    // they need not trust Pool contracts in any way: all security checks are made by the Vault. They must however be
    // aware of the Pools' pricing algorithms in order to estimate the prices Pools will quote.
    //
    // The `swap` function executes a single swap, while `batchSwap` can perform multiple swaps in sequence.
    // In each individual swap, tokens of one kind are sent from the sender to the Pool (this is the 'token in'),
    // and tokens of another kind are sent from the Pool to the recipient in exchange (this is the 'token out').
    // More complex swaps, such as one token in to multiple tokens out can be achieved by batching together
    // individual swaps.
    //
    // There are two swap kinds:
    //  - 'given in' swaps, where the amount of tokens in (sent to the Pool) is known, and the Pool determines (via the
    // `onSwap` hook) the amount of tokens out (to send to the recipient).
    //  - 'given out' swaps, where the amount of tokens out (received from the Pool) is known, and the Pool determines
    // (via the `onSwap` hook) the amount of tokens in (to receive from the sender).
    //
    // Additionally, it is possible to chain swaps using a placeholder input amount, which the Vault replaces with
    // the calculated output of the previous swap. If the previous swap was 'given in', this will be the calculated
    // tokenOut amount. If the previous swap was 'given out', it will use the calculated tokenIn amount. These extended
    // swaps are known as 'multihop' swaps, since they 'hop' through a number of intermediate tokens before arriving at
    // the final intended token.
    //
    // In all cases, tokens are only transferred in and out of the Vault (or withdrawn from and deposited into Internal
    // Balance) after all individual swaps have been completed, and the net token balance change computed. This makes
    // certain swap patterns, such as multihops, or swaps that interact with the same token pair in multiple Pools, cost
    // much less gas than they would otherwise.
    //
    // It also means that under certain conditions it is possible to perform arbitrage by swapping with multiple
    // Pools in a way that results in net token movement out of the Vault (profit), with no tokens being sent in (only
    // updating the Pool's internal accounting).
    //
    // To protect users from front-running or the market changing rapidly, they supply a list of 'limits' for each token
    // involved in the swap, where either the maximum number of tokens to send (by passing a positive value) or the
    // minimum amount of tokens to receive (by passing a negative value) is specified.
    //
    // Additionally, a 'deadline' timestamp can also be provided, forcing the swap to fail if it occurs after
    // this point in time (e.g. if the transaction failed to be included in a block promptly).
    //
    // If interacting with Pools that hold WETH, it is possible to both send and receive ETH directly: the Vault will do
    // the wrapping and unwrapping. To enable this mechanism, the IAsset sentinel value (the zero address) must be
    // passed in the `assets` array instead of the WETH address. Note that it is possible to combine ETH and WETH in the
    // same swap. Any excess ETH will be sent back to the caller (not the sender, which is relevant for relayers).
    //
    // Finally, Internal Balance can be used when either sending or receiving tokens.

    enum SwapKind {
        GIVEN_IN,
        GIVEN_OUT
    }

    /**
     * @dev Performs a swap with a single Pool.
     *
     * If the swap is 'given in' (the number of tokens to send to the Pool is known), it returns the amount of tokens
     * taken from the Pool, which must be greater than or equal to `limit`.
     *
     * If the swap is 'given out' (the number of tokens to take from the Pool is known), it returns the amount of tokens
     * sent to the Pool, which must be less than or equal to `limit`.
     *
     * Internal Balance usage and the recipient are determined by the `funds` struct.
     *
     * Emits a `Swap` event.
     */
    function swap(
        SingleSwap memory singleSwap,
        FundManagement memory funds,
        uint256 limit,
        uint256 deadline
    ) external payable returns (uint256);

    /**
     * @dev Data for a single swap executed by `swap`. `amount` is either `amountIn` or `amountOut` depending on
     * the `kind` value.
     *
     * `assetIn` and `assetOut` are either token addresses, or the IAsset sentinel value for ETH (the zero address).
     * Note that Pools never interact with ETH directly: it will be wrapped to or unwrapped from WETH by the Vault.
     *
     * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be
     * used to extend swap behavior.
     */
    struct SingleSwap {
        bytes32 poolId;
        SwapKind kind;
        IERC20 assetIn;
        IERC20 assetOut;
        uint256 amount;
        bytes userData;
    }

    /**
     * @dev Performs a series of swaps with one or multiple Pools. In each individual swap, the caller determines either
     * the amount of tokens sent to or received from the Pool, depending on the `kind` value.
     *
     * Returns an array with the net Vault asset balance deltas. Positive amounts represent tokens (or ETH) sent to the
     * Vault, and negative amounts represent tokens (or ETH) sent by the Vault. Each delta corresponds to the asset at
     * the same index in the `assets` array.
     *
     * Swaps are executed sequentially, in the order specified by the `swaps` array. Each array element describes a
     * Pool, the token to be sent to this Pool, the token to receive from it, and an amount that is either `amountIn` or
     * `amountOut` depending on the swap kind.
     *
     * Multihop swaps can be executed by passing an `amount` value of zero for a swap. This will cause the amount in/out
     * of the previous swap to be used as the amount in for the current one. In a 'given in' swap, 'tokenIn' must equal
     * the previous swap's `tokenOut`. For a 'given out' swap, `tokenOut` must equal the previous swap's `tokenIn`.
     *
     * The `assets` array contains the addresses of all assets involved in the swaps. These are either token addresses,
     * or the IAsset sentinel value for ETH (the zero address). Each entry in the `swaps` array specifies tokens in and
     * out by referencing an index in `assets`. Note that Pools never interact with ETH directly: it will be wrapped to
     * or unwrapped from WETH by the Vault.
     *
     * Internal Balance usage, sender, and recipient are determined by the `funds` struct. The `limits` array specifies
     * the minimum or maximum amount of each token the vault is allowed to transfer.
     *
     * `batchSwap` can be used to make a single swap, like `swap` does, but doing so requires more gas than the
     * equivalent `swap` call.
     *
     * Emits `Swap` events.
     */
    function batchSwap(
        SwapKind kind,
        BatchSwapStep[] memory swaps,
        IERC20[] memory assets,
        FundManagement memory funds,
        int256[] memory limits,
        uint256 deadline
    ) external payable returns (int256[] memory);

    /**
     * @dev Data for each individual swap executed by `batchSwap`. The asset in and out fields are indexes into the
     * `assets` array passed to that function, and ETH assets are converted to WETH.
     *
     * If `amount` is zero, the multihop mechanism is used to determine the actual amount based on the amount in/out
     * from the previous swap, depending on the swap kind.
     *
     * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be
     * used to extend swap behavior.
     */
    struct BatchSwapStep {
        bytes32 poolId;
        uint256 assetInIndex;
        uint256 assetOutIndex;
        uint256 amount;
        bytes userData;
    }

    /**
     * @dev All tokens in a swap are either sent from the `sender` account to the Vault, or from the Vault to the
     * `recipient` account.
     *
     * If the caller is not `sender`, it must be an authorized relayer for them.
     *
     * If `fromInternalBalance` is true, the `sender`'s Internal Balance will be preferred, performing an ERC20
     * transfer for the difference between the requested amount and the User's Internal Balance (if any). The `sender`
     * must have allowed the Vault to use their tokens via `IERC20.approve()`. This matches the behavior of
     * `joinPool`.
     *
     * If `toInternalBalance` is true, tokens will be deposited to `recipient`'s internal balance instead of
     * transferred. This matches the behavior of `exitPool`.
     *
     * Note that ETH cannot be deposited to or withdrawn from Internal Balance: attempting to do so will trigger a
     * revert.
     */
    struct FundManagement {
        address sender;
        bool fromInternalBalance;
        address payable recipient;
        bool toInternalBalance;
    }
}

File 4 of 6 : GPv2Order.sol
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.7.6;

import "../interfaces/IERC20.sol";

/// @title Gnosis Protocol v2 Order Library
/// @author Gnosis Developers
library GPv2Order {
    /// @dev The complete data for a Gnosis Protocol order. This struct contains
    /// all order parameters that are signed for submitting to GP.
    struct Data {
        IERC20 sellToken;
        IERC20 buyToken;
        address receiver;
        uint256 sellAmount;
        uint256 buyAmount;
        uint32 validTo;
        bytes32 appData;
        uint256 feeAmount;
        bytes32 kind;
        bool partiallyFillable;
        bytes32 sellTokenBalance;
        bytes32 buyTokenBalance;
    }

    /// @dev The order EIP-712 type hash for the [`GPv2Order.Data`] struct.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256(
    ///     "Order(" +
    ///         "address sellToken," +
    ///         "address buyToken," +
    ///         "address receiver," +
    ///         "uint256 sellAmount," +
    ///         "uint256 buyAmount," +
    ///         "uint32 validTo," +
    ///         "bytes32 appData," +
    ///         "uint256 feeAmount," +
    ///         "string kind," +
    ///         "bool partiallyFillable," +
    ///         "string sellTokenBalance," +
    ///         "string buyTokenBalance" +
    ///     ")"
    /// )
    /// ```
    bytes32 internal constant TYPE_HASH =
        hex"d5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e489";

    /// @dev The marker value for a sell order for computing the order struct
    /// hash. This allows the EIP-712 compatible wallets to display a
    /// descriptive string for the order kind (instead of 0 or 1).
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("sell")
    /// ```
    bytes32 internal constant KIND_SELL =
        hex"f3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee346775";

    /// @dev The OrderKind marker value for a buy order for computing the order
    /// struct hash.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("buy")
    /// ```
    bytes32 internal constant KIND_BUY =
        hex"6ed88e868af0a1983e3886d5f3e95a2fafbd6c3450bc229e27342283dc429ccc";

    /// @dev The TokenBalance marker value for using direct ERC20 balances for
    /// computing the order struct hash.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("erc20")
    /// ```
    bytes32 internal constant BALANCE_ERC20 =
        hex"5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9";

    /// @dev The TokenBalance marker value for using Balancer Vault external
    /// balances (in order to re-use Vault ERC20 approvals) for computing the
    /// order struct hash.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("external")
    /// ```
    bytes32 internal constant BALANCE_EXTERNAL =
        hex"abee3b73373acd583a130924aad6dc38cfdc44ba0555ba94ce2ff63980ea0632";

    /// @dev The TokenBalance marker value for using Balancer Vault internal
    /// balances for computing the order struct hash.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("internal")
    /// ```
    bytes32 internal constant BALANCE_INTERNAL =
        hex"4ac99ace14ee0a5ef932dc609df0943ab7ac16b7583634612f8dc35a4289a6ce";

    /// @dev Marker address used to indicate that the receiver of the trade
    /// proceeds should the owner of the order.
    ///
    /// This is chosen to be `address(0)` for gas efficiency as it is expected
    /// to be the most common case.
    address internal constant RECEIVER_SAME_AS_OWNER = address(0);

    /// @dev The byte length of an order unique identifier.
    uint256 internal constant UID_LENGTH = 56;

    /// @dev Returns the actual receiver for an order. This function checks
    /// whether or not the [`receiver`] field uses the marker value to indicate
    /// it is the same as the order owner.
    ///
    /// @return receiver The actual receiver of trade proceeds.
    function actualReceiver(
        Data memory order,
        address owner
    ) internal pure returns (address receiver) {
        if (order.receiver == RECEIVER_SAME_AS_OWNER) {
            receiver = owner;
        } else {
            receiver = order.receiver;
        }
    }

    /// @dev Return the EIP-712 signing hash for the specified order.
    ///
    /// @param order The order to compute the EIP-712 signing hash for.
    /// @param domainSeparator The EIP-712 domain separator to use.
    /// @return orderDigest The 32 byte EIP-712 struct hash.
    function hash(
        Data memory order,
        bytes32 domainSeparator
    ) internal pure returns (bytes32 orderDigest) {
        bytes32 structHash;

        // NOTE: Compute the EIP-712 order struct hash in place. As suggested
        // in the EIP proposal, noting that the order struct has 12 fields, and
        // prefixing the type hash `(1 + 12) * 32 = 416` bytes to hash.
        // <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#rationale-for-encodedata>
        // solhint-disable-next-line no-inline-assembly
        assembly {
            let dataStart := sub(order, 32)
            let temp := mload(dataStart)
            mstore(dataStart, TYPE_HASH)
            structHash := keccak256(dataStart, 416)
            mstore(dataStart, temp)
        }

        // NOTE: Now that we have the struct hash, compute the EIP-712 signing
        // hash using scratch memory past the free memory pointer. The signing
        // hash is computed from `"\x19\x01" || domainSeparator || structHash`.
        // <https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html#layout-in-memory>
        // <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#specification>
        // solhint-disable-next-line no-inline-assembly
        assembly {
            let freeMemoryPointer := mload(0x40)
            mstore(freeMemoryPointer, "\x19\x01")
            mstore(add(freeMemoryPointer, 2), domainSeparator)
            mstore(add(freeMemoryPointer, 34), structHash)
            orderDigest := keccak256(freeMemoryPointer, 66)
        }
    }

    /// @dev Packs order UID parameters into the specified memory location. The
    /// result is equivalent to `abi.encodePacked(...)` with the difference that
    /// it allows re-using the memory for packing the order UID.
    ///
    /// This function reverts if the order UID buffer is not the correct size.
    ///
    /// @param orderUid The buffer pack the order UID parameters into.
    /// @param orderDigest The EIP-712 struct digest derived from the order
    /// parameters.
    /// @param owner The address of the user who owns this order.
    /// @param validTo The epoch time at which the order will stop being valid.
    function packOrderUidParams(
        bytes memory orderUid,
        bytes32 orderDigest,
        address owner,
        uint32 validTo
    ) internal pure {
        require(orderUid.length == UID_LENGTH, "GPv2: uid buffer overflow");

        // NOTE: Write the order UID to the allocated memory buffer. The order
        // parameters are written to memory in **reverse order** as memory
        // operations write 32-bytes at a time and we want to use a packed
        // encoding. This means, for example, that after writing the value of
        // `owner` to bytes `20:52`, writing the `orderDigest` to bytes `0:32`
        // will **overwrite** bytes `20:32`. This is desirable as addresses are
        // only 20 bytes and `20:32` should be `0`s:
        //
        //        |           1111111111222222222233333333334444444444555555
        //   byte | 01234567890123456789012345678901234567890123456789012345
        // -------+---------------------------------------------------------
        //  field | [.........orderDigest..........][......owner.......][vT]
        // -------+---------------------------------------------------------
        // mstore |                         [000000000000000000000000000.vT]
        //        |                     [00000000000.......owner.......]
        //        | [.........orderDigest..........]
        //
        // Additionally, since Solidity `bytes memory` are length prefixed,
        // 32 needs to be added to all the offsets.
        //
        // solhint-disable-next-line no-inline-assembly
        assembly {
            mstore(add(orderUid, 56), validTo)
            mstore(add(orderUid, 52), owner)
            mstore(add(orderUid, 32), orderDigest)
        }
    }

    /// @dev Extracts specific order information from the standardized unique
    /// order id of the protocol.
    ///
    /// @param orderUid The unique identifier used to represent an order in
    /// the protocol. This uid is the packed concatenation of the order digest,
    /// the validTo order parameter and the address of the user who created the
    /// order. It is used by the user to interface with the contract directly,
    /// and not by calls that are triggered by the solvers.
    /// @return orderDigest The EIP-712 signing digest derived from the order
    /// parameters.
    /// @return owner The address of the user who owns this order.
    /// @return validTo The epoch time at which the order will stop being valid.
    function extractOrderUidParams(
        bytes calldata orderUid
    )
        internal
        pure
        returns (bytes32 orderDigest, address owner, uint32 validTo)
    {
        require(orderUid.length == UID_LENGTH, "GPv2: invalid uid");

        // Use assembly to efficiently decode packed calldata.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            orderDigest := calldataload(orderUid.offset)
            owner := shr(96, calldataload(add(orderUid.offset, 32)))
            validTo := shr(224, calldataload(add(orderUid.offset, 52)))
        }
    }
}

File 5 of 6 : GPv2SafeERC20.sol
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.7.6;

import "../interfaces/IERC20.sol";

/// @title Gnosis Protocol v2 Safe ERC20 Transfer Library
/// @author Gnosis Developers
/// @dev Gas-efficient version of Openzeppelin's SafeERC20 contract.
library GPv2SafeERC20 {
    /// @dev Wrapper around a call to the ERC20 function `transfer` that reverts
    /// also when the token returns `false`.
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        bytes4 selector_ = token.transfer.selector;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            let freeMemoryPointer := mload(0x40)
            mstore(freeMemoryPointer, selector_)
            mstore(
                add(freeMemoryPointer, 4),
                and(to, 0xffffffffffffffffffffffffffffffffffffffff)
            )
            mstore(add(freeMemoryPointer, 36), value)

            if iszero(call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)) {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }
        }

        require(getLastTransferResult(token), "GPv2: failed transfer");
    }

    /// @dev Wrapper around a call to the ERC20 function `transferFrom` that
    /// reverts also when the token returns `false`.
    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        bytes4 selector_ = token.transferFrom.selector;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            let freeMemoryPointer := mload(0x40)
            mstore(freeMemoryPointer, selector_)
            mstore(
                add(freeMemoryPointer, 4),
                and(from, 0xffffffffffffffffffffffffffffffffffffffff)
            )
            mstore(
                add(freeMemoryPointer, 36),
                and(to, 0xffffffffffffffffffffffffffffffffffffffff)
            )
            mstore(add(freeMemoryPointer, 68), value)

            if iszero(call(gas(), token, 0, freeMemoryPointer, 100, 0, 0)) {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }
        }

        require(getLastTransferResult(token), "GPv2: failed transferFrom");
    }

    /// @dev Verifies that the last return was a successful `transfer*` call.
    /// This is done by checking that the return data is either empty, or
    /// is a valid ABI encoded boolean.
    function getLastTransferResult(
        IERC20 token
    ) private view returns (bool success) {
        // NOTE: Inspecting previous return data requires assembly. Note that
        // we write the return data to memory 0 in the case where the return
        // data size is 32, this is OK since the first 64 bytes of memory are
        // reserved by Solidy as a scratch space that can be used within
        // assembly blocks.
        // <https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html>
        // solhint-disable-next-line no-inline-assembly
        assembly {
            /// @dev Revert with an ABI encoded Solidity error with a message
            /// that fits into 32-bytes.
            ///
            /// An ABI encoded Solidity error has the following memory layout:
            ///
            /// ------------+----------------------------------
            ///  byte range | value
            /// ------------+----------------------------------
            ///  0x00..0x04 |        selector("Error(string)")
            ///  0x04..0x24 |      string offset (always 0x20)
            ///  0x24..0x44 |                    string length
            ///  0x44..0x64 | string value, padded to 32-bytes
            function revertWithMessage(length, message) {
                mstore(0x00, "\x08\xc3\x79\xa0")
                mstore(0x04, 0x20)
                mstore(0x24, length)
                mstore(0x44, message)
                revert(0x00, 0x64)
            }

            switch returndatasize()
            // Non-standard ERC20 transfer without return.
            case 0 {
                // NOTE: When the return data size is 0, verify that there
                // is code at the address. This is done in order to maintain
                // compatibility with Solidity calling conventions.
                // <https://docs.soliditylang.org/en/v0.7.6/control-structures.html#external-function-calls>
                if iszero(extcodesize(token)) {
                    revertWithMessage(20, "GPv2: not a contract")
                }

                success := 1
            }
            // Standard ERC20 transfer returning boolean success value.
            case 32 {
                returndatacopy(0, 0, returndatasize())

                // NOTE: For ABI encoding v1, any non-zero value is accepted
                // as `true` for a boolean. In order to stay compatible with
                // OpenZeppelin's `SafeERC20` library which is known to work
                // with the existing ERC20 implementation we care about,
                // make sure we return success for any non-zero return value
                // from the `transfer*` call.
                success := iszero(iszero(mload(0)))
            }
            default {
                revertWithMessage(31, "GPv2: malformed transfer result")
            }
        }
    }
}

File 6 of 6 : GPv2Transfer.sol
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.7.6;
pragma abicoder v2;

import "../interfaces/IERC20.sol";
import "../interfaces/IVault.sol";
import "./GPv2Order.sol";
import "./GPv2SafeERC20.sol";

/// @title Gnosis Protocol v2 Transfers
/// @author Gnosis Developers
library GPv2Transfer {
    using GPv2SafeERC20 for IERC20;

    /// @dev Transfer data.
    struct Data {
        address account;
        IERC20 token;
        uint256 amount;
        bytes32 balance;
    }

    /// @dev Ether marker address used to indicate an Ether transfer.
    address internal constant BUY_ETH_ADDRESS =
        0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

    /// @dev Execute the specified transfer from the specified account to a
    /// recipient. The recipient will either receive internal Vault balances or
    /// ERC20 token balances depending on whether the account is using internal
    /// balances or not.
    ///
    /// This method is used for transferring fees to the settlement contract
    /// when settling a single order directly with Balancer.
    ///
    /// Note that this method is subtly different from `transferFromAccounts`
    /// with a single transfer with respect to how it deals with internal
    /// balances. Specifically, this method will perform an **internal balance
    /// transfer to the settlement contract instead of a withdrawal to the
    /// external balance of the settlement contract** for trades that specify
    /// trading with internal balances. This is done as a gas optimization in
    /// the single order "fast-path".
    ///
    /// @param vault The Balancer vault to use.
    /// @param transfer The transfer to perform specifying the sender account.
    /// @param recipient The recipient for the transfer.
    function fastTransferFromAccount(
        IVault vault,
        Data calldata transfer,
        address recipient
    ) internal {
        require(
            address(transfer.token) != BUY_ETH_ADDRESS,
            "GPv2: cannot transfer native ETH"
        );

        if (transfer.balance == GPv2Order.BALANCE_ERC20) {
            transfer.token.safeTransferFrom(
                transfer.account,
                recipient,
                transfer.amount
            );
        } else {
            IVault.UserBalanceOp[]
                memory balanceOps = new IVault.UserBalanceOp[](1);

            IVault.UserBalanceOp memory balanceOp = balanceOps[0];
            balanceOp.kind = transfer.balance == GPv2Order.BALANCE_EXTERNAL
                ? IVault.UserBalanceOpKind.TRANSFER_EXTERNAL
                : IVault.UserBalanceOpKind.TRANSFER_INTERNAL;
            balanceOp.asset = transfer.token;
            balanceOp.amount = transfer.amount;
            balanceOp.sender = transfer.account;
            balanceOp.recipient = payable(recipient);

            vault.manageUserBalance(balanceOps);
        }
    }

    /// @dev Execute the specified transfers from the specified accounts to a
    /// single recipient. The recipient will receive all transfers as ERC20
    /// token balances, regardless of whether or not the accounts are using
    /// internal Vault balances.
    ///
    /// This method is used for accumulating user balances into the settlement
    /// contract.
    ///
    /// @param vault The Balancer vault to use.
    /// @param transfers The batched transfers to perform specifying the
    /// sender accounts.
    /// @param recipient The single recipient for all the transfers.
    function transferFromAccounts(
        IVault vault,
        Data[] calldata transfers,
        address recipient
    ) internal {
        // NOTE: Allocate buffer of Vault balance operations large enough to
        // hold all GP transfers. This is done to avoid re-allocations (which
        // are gas inefficient) while still allowing all transfers to be batched
        // into a single Vault call.
        IVault.UserBalanceOp[] memory balanceOps = new IVault.UserBalanceOp[](
            transfers.length
        );
        uint256 balanceOpCount = 0;

        for (uint256 i = 0; i < transfers.length; i++) {
            Data calldata transfer = transfers[i];
            require(
                address(transfer.token) != BUY_ETH_ADDRESS,
                "GPv2: cannot transfer native ETH"
            );

            if (transfer.balance == GPv2Order.BALANCE_ERC20) {
                transfer.token.safeTransferFrom(
                    transfer.account,
                    recipient,
                    transfer.amount
                );
            } else {
                IVault.UserBalanceOp memory balanceOp = balanceOps[
                    balanceOpCount++
                ];
                balanceOp.kind = transfer.balance == GPv2Order.BALANCE_EXTERNAL
                    ? IVault.UserBalanceOpKind.TRANSFER_EXTERNAL
                    : IVault.UserBalanceOpKind.WITHDRAW_INTERNAL;
                balanceOp.asset = transfer.token;
                balanceOp.amount = transfer.amount;
                balanceOp.sender = transfer.account;
                balanceOp.recipient = payable(recipient);
            }
        }

        if (balanceOpCount > 0) {
            truncateBalanceOpsArray(balanceOps, balanceOpCount);
            vault.manageUserBalance(balanceOps);
        }
    }

    /// @dev Execute the specified transfers to their respective accounts.
    ///
    /// This method is used for paying out trade proceeds from the settlement
    /// contract.
    ///
    /// @param vault The Balancer vault to use.
    /// @param transfers The batched transfers to perform.
    function transferToAccounts(
        IVault vault,
        Data[] memory transfers
    ) internal {
        IVault.UserBalanceOp[] memory balanceOps = new IVault.UserBalanceOp[](
            transfers.length
        );
        uint256 balanceOpCount = 0;

        for (uint256 i = 0; i < transfers.length; i++) {
            Data memory transfer = transfers[i];

            if (address(transfer.token) == BUY_ETH_ADDRESS) {
                require(
                    transfer.balance != GPv2Order.BALANCE_INTERNAL,
                    "GPv2: unsupported internal ETH"
                );
                payable(transfer.account).transfer(transfer.amount);
            } else if (transfer.balance == GPv2Order.BALANCE_ERC20) {
                transfer.token.safeTransfer(transfer.account, transfer.amount);
            } else {
                IVault.UserBalanceOp memory balanceOp = balanceOps[
                    balanceOpCount++
                ];
                balanceOp.kind = IVault.UserBalanceOpKind.DEPOSIT_INTERNAL;
                balanceOp.asset = transfer.token;
                balanceOp.amount = transfer.amount;
                balanceOp.sender = address(this);
                balanceOp.recipient = payable(transfer.account);
            }
        }

        if (balanceOpCount > 0) {
            truncateBalanceOpsArray(balanceOps, balanceOpCount);
            vault.manageUserBalance(balanceOps);
        }
    }

    /// @dev Truncate a Vault balance operation array to its actual size.
    ///
    /// This method **does not** check whether or not the new length is valid,
    /// and specifying a size that is larger than the array's actual length is
    /// undefined behaviour.
    ///
    /// @param balanceOps The memory array of balance operations to truncate.
    /// @param newLength The new length to set.
    function truncateBalanceOpsArray(
        IVault.UserBalanceOp[] memory balanceOps,
        uint256 newLength
    ) private pure {
        // NOTE: Truncate the vault transfers array to the specified length.
        // This is done by setting the array's length which occupies the first
        // word in memory pointed to by the `balanceOps` memory variable.
        // <https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html>
        // solhint-disable-next-line no-inline-assembly
        assembly {
            mstore(balanceOps, newLength)
        }
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IVault","name":"vault_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"enum IVault.SwapKind","name":"kind","type":"uint8"},{"components":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"uint256","name":"assetInIndex","type":"uint256"},{"internalType":"uint256","name":"assetOutIndex","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"internalType":"struct IVault.BatchSwapStep[]","name":"swaps","type":"tuple[]"},{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"bool","name":"fromInternalBalance","type":"bool"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"bool","name":"toInternalBalance","type":"bool"}],"internalType":"struct IVault.FundManagement","name":"funds","type":"tuple"},{"internalType":"int256[]","name":"limits","type":"int256[]"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"balance","type":"bytes32"}],"internalType":"struct GPv2Transfer.Data","name":"feeTransfer","type":"tuple"}],"name":"batchSwapWithFee","outputs":[{"internalType":"int256[]","name":"tokenDeltas","type":"int256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"balance","type":"bytes32"}],"internalType":"struct GPv2Transfer.Data[]","name":"transfers","type":"tuple[]"}],"name":"transferFromAccounts","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c060405234801561001057600080fd5b5060405161129e38038061129e83398101604081905261002f9161004b565b33606090811b6080521b6001600160601b03191660a052610079565b60006020828403121561005c578081fd5b81516001600160a01b0381168114610072578182fd5b9392505050565b60805160601c60a05160601c6111ee6100b060003980610130528061020152806102bd5250806093528061024c52506111ee6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80634817a2861461003b5780637d10d11f14610064575b600080fd5b61004e610049366004610cd9565b610079565b60405161005b9190610eb3565b60405180910390f35b610077610072366004610c69565b610234565b005b60603373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146100f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100ea906110e5565b60405180910390fd5b6040517f945bcec900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063945bcec990610171908c908c908c908c908c908c908c90600401610f59565b600060405180830381600087803b15801561018b57600080fd5b505af115801561019f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526101e59190810190610bd9565b905061022873ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001683336102e9565b98975050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146102a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100ea906110e5565b6102e573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016838333610551565b5050565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee61030e6040840160208501610bb6565b73ffffffffffffffffffffffffffffffffffffffff16141561035c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100ea9061111c565b7f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9826060013514156103d0576103cb6103986020840184610bb6565b82604085018035906103ad9060208801610bb6565b73ffffffffffffffffffffffffffffffffffffffff16929190610816565b61054c565b604080516001808252818301909252600091816020015b6103ef6109cb565b8152602001906001900390816103e757905050905060008160008151811061041357fe5b602002602001015190507fabee3b73373acd583a130924aad6dc38cfdc44ba0555ba94ce2ff63980ea063284606001351461044f576002610452565b60035b8190600381111561045f57fe5b9081600381111561046c57fe5b90525061047f6040850160208601610bb6565b73ffffffffffffffffffffffffffffffffffffffff16602080830191909152604080860135908301526104b490850185610bb6565b73ffffffffffffffffffffffffffffffffffffffff908116606083015283811660808301526040517f0e8e3e8400000000000000000000000000000000000000000000000000000000815290861690630e8e3e8490610517908590600401610ec6565b600060405180830381600087803b15801561053157600080fd5b505af1158015610545573d6000803e3d6000fd5b5050505050505b505050565b60008267ffffffffffffffff8111801561056a57600080fd5b506040519080825280602002602001820160405280156105a457816020015b6105916109cb565b8152602001906001900390816105895790505b5090506000805b8481101561077857368686838181106105c057fe5b60800291909101915073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90506105f06040830160208401610bb6565b73ffffffffffffffffffffffffffffffffffffffff16141561063e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100ea9061111c565b7f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9816060013514156106945761068f61067a6020830183610bb6565b86604084018035906103ad9060208701610bb6565b61076f565b60008484806001019550815181106106a857fe5b602002602001015190507fabee3b73373acd583a130924aad6dc38cfdc44ba0555ba94ce2ff63980ea06328260600135146106e45760016106e7565b60035b819060038111156106f457fe5b9081600381111561070157fe5b9052506107146040830160208401610bb6565b73ffffffffffffffffffffffffffffffffffffffff166020808301919091526040808401359083015261074990830183610bb6565b73ffffffffffffffffffffffffffffffffffffffff908116606083015286166080909101525b506001016105ab565b50801561080e5761078982826108fd565b6040517f0e8e3e8400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871690630e8e3e84906107db908590600401610ec6565b600060405180830381600087803b1580156107f557600080fd5b505af1158015610809573d6000803e3d6000fd5b505050505b505050505050565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff8581166004840152841660248301526044820183905290600080606483828a5af1610881573d6000803e3d6000fd5b5061088b85610901565b6108f657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f475076323a206661696c6564207472616e7366657246726f6d00000000000000604482015290519081900360640190fd5b5050505050565b9052565b600061093f565b7f08c379a0000000000000000000000000000000000000000000000000000000006000526020600452806024528160445260646000fd5b3d801561097e57602081146109b8576109797f475076323a206d616c666f726d6564207472616e7366657220726573756c7400601f610908565b6109c5565b823b6109af576109af7f475076323a206e6f74206120636f6e74726163740000000000000000000000006014610908565b600191506109c5565b3d6000803e600051151591505b50919050565b6040805160a081019091528060008152600060208201819052604082018190526060820181905260809091015290565b600082601f830112610a0b578081fd5b81356020610a20610a1b83611175565b611151565b8281528181019085830183850287018401881015610a3c578586fd5b855b85811015610a63578135610a5181611193565b84529284019290840190600101610a3e565b5090979650505050505050565b600082601f830112610a80578081fd5b81356020610a90610a1b83611175565b8281528181019085830183850287018401881015610aac578586fd5b855b85811015610a6357813584529284019290840190600101610aae565b60008083601f840112610adb578182fd5b50813567ffffffffffffffff811115610af2578182fd5b6020830191508360208083028501011115610b0c57600080fd5b9250929050565b80358015158114610b2357600080fd5b919050565b6000608082840312156109c5578081fd5b600060808284031215610b4a578081fd5b6040516080810181811067ffffffffffffffff82111715610b6757fe5b6040529050808235610b7881611193565b8152610b8660208401610b13565b60208201526040830135610b9981611193565b6040820152610baa60608401610b13565b60608201525092915050565b600060208284031215610bc7578081fd5b8135610bd281611193565b9392505050565b60006020808385031215610beb578182fd5b825167ffffffffffffffff811115610c01578283fd5b8301601f81018513610c11578283fd5b8051610c1f610a1b82611175565b8181528381019083850185840285018601891015610c3b578687fd5b8694505b83851015610c5d578051835260019490940193918501918501610c3f565b50979650505050505050565b60008060208385031215610c7b578081fd5b823567ffffffffffffffff80821115610c92578283fd5b818501915085601f830112610ca5578283fd5b813581811115610cb3578384fd5b866020608083028501011115610cc7578384fd5b60209290920196919550909350505050565b6000806000806000806000806101a0898b031215610cf5578384fd5b883560028110610d03578485fd5b9750602089013567ffffffffffffffff80821115610d1f578586fd5b610d2b8c838d01610aca565b909950975060408b0135915080821115610d43578586fd5b610d4f8c838d016109fb565b9650610d5e8c60608d01610b39565b955060e08b0135915080821115610d73578485fd5b50610d808b828c01610a70565b9350506101008901359150610d998a6101208b01610b28565b90509295985092959890939650565b6000815180845260208085019450808401835b83811015610ded57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101610dbb565b509495945050505050565b6000815180845260208085019450808401835b83811015610ded57815187529582019590820190600101610e0b565b600082845282826020860137806020848601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011685010190509392505050565b73ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152506060810151151560608301525050565b600060208252610bd26020830184610df8565b602080825282518282018190526000919060409081850190868401855b82811015610f4c578151805160048110610ef957fe5b85528087015173ffffffffffffffffffffffffffffffffffffffff908116888701528682015187870152606080830151821690870152608091820151169085015260a09093019290850190600101610ee3565b5091979650505050505050565b600061012080830160028b10610f6b57fe5b8a8452602080850192909252889052610140808401918981028501909101908a845b8b811015611098577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec087850301855281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618e3603018112610fed578687fd5b8d01803585528381013584860152604080820135908601526060808201359086015260a0608080830135368490037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe101811261104757898afd5b8301803567ffffffffffffffff81111561105f578a8bfd5b80360385131561106d578a8bfd5b83838a0152611081848a01828a8501610e27565b998801999850505093850193505050600101610f8d565b50505083810360408501526110ad8189610da8565b9150506110bd6060840187610e6f565b82810360e08401526110cf8186610df8565b9150508261010083015298975050505050505050565b60208082526011908201527f475076323a206e6f742063726561746f72000000000000000000000000000000604082015260600190565b6020808252818101527f475076323a2063616e6e6f74207472616e73666572206e617469766520455448604082015260600190565b60405181810167ffffffffffffffff8111828210171561116d57fe5b604052919050565b600067ffffffffffffffff82111561118957fe5b5060209081020190565b73ffffffffffffffffffffffffffffffffffffffff811681146111b557600080fd5b5056fea2646970667358221220364a6941bea69620b7dc3a957d0ab4cbf3bfc459c7ad3924d220620aca9202fc64736f6c63430007060033000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100365760003560e01c80634817a2861461003b5780637d10d11f14610064575b600080fd5b61004e610049366004610cd9565b610079565b60405161005b9190610eb3565b60405180910390f35b610077610072366004610c69565b610234565b005b60603373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab4116146100f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100ea906110e5565b60405180910390fd5b6040517f945bcec900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8169063945bcec990610171908c908c908c908c908c908c908c90600401610f59565b600060405180830381600087803b15801561018b57600080fd5b505af115801561019f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526101e59190810190610bd9565b905061022873ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c81683336102e9565b98975050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab4116146102a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100ea906110e5565b6102e573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c816838333610551565b5050565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee61030e6040840160208501610bb6565b73ffffffffffffffffffffffffffffffffffffffff16141561035c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100ea9061111c565b7f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9826060013514156103d0576103cb6103986020840184610bb6565b82604085018035906103ad9060208801610bb6565b73ffffffffffffffffffffffffffffffffffffffff16929190610816565b61054c565b604080516001808252818301909252600091816020015b6103ef6109cb565b8152602001906001900390816103e757905050905060008160008151811061041357fe5b602002602001015190507fabee3b73373acd583a130924aad6dc38cfdc44ba0555ba94ce2ff63980ea063284606001351461044f576002610452565b60035b8190600381111561045f57fe5b9081600381111561046c57fe5b90525061047f6040850160208601610bb6565b73ffffffffffffffffffffffffffffffffffffffff16602080830191909152604080860135908301526104b490850185610bb6565b73ffffffffffffffffffffffffffffffffffffffff908116606083015283811660808301526040517f0e8e3e8400000000000000000000000000000000000000000000000000000000815290861690630e8e3e8490610517908590600401610ec6565b600060405180830381600087803b15801561053157600080fd5b505af1158015610545573d6000803e3d6000fd5b5050505050505b505050565b60008267ffffffffffffffff8111801561056a57600080fd5b506040519080825280602002602001820160405280156105a457816020015b6105916109cb565b8152602001906001900390816105895790505b5090506000805b8481101561077857368686838181106105c057fe5b60800291909101915073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90506105f06040830160208401610bb6565b73ffffffffffffffffffffffffffffffffffffffff16141561063e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100ea9061111c565b7f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9816060013514156106945761068f61067a6020830183610bb6565b86604084018035906103ad9060208701610bb6565b61076f565b60008484806001019550815181106106a857fe5b602002602001015190507fabee3b73373acd583a130924aad6dc38cfdc44ba0555ba94ce2ff63980ea06328260600135146106e45760016106e7565b60035b819060038111156106f457fe5b9081600381111561070157fe5b9052506107146040830160208401610bb6565b73ffffffffffffffffffffffffffffffffffffffff166020808301919091526040808401359083015261074990830183610bb6565b73ffffffffffffffffffffffffffffffffffffffff908116606083015286166080909101525b506001016105ab565b50801561080e5761078982826108fd565b6040517f0e8e3e8400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871690630e8e3e84906107db908590600401610ec6565b600060405180830381600087803b1580156107f557600080fd5b505af1158015610809573d6000803e3d6000fd5b505050505b505050505050565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff8581166004840152841660248301526044820183905290600080606483828a5af1610881573d6000803e3d6000fd5b5061088b85610901565b6108f657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f475076323a206661696c6564207472616e7366657246726f6d00000000000000604482015290519081900360640190fd5b5050505050565b9052565b600061093f565b7f08c379a0000000000000000000000000000000000000000000000000000000006000526020600452806024528160445260646000fd5b3d801561097e57602081146109b8576109797f475076323a206d616c666f726d6564207472616e7366657220726573756c7400601f610908565b6109c5565b823b6109af576109af7f475076323a206e6f74206120636f6e74726163740000000000000000000000006014610908565b600191506109c5565b3d6000803e600051151591505b50919050565b6040805160a081019091528060008152600060208201819052604082018190526060820181905260809091015290565b600082601f830112610a0b578081fd5b81356020610a20610a1b83611175565b611151565b8281528181019085830183850287018401881015610a3c578586fd5b855b85811015610a63578135610a5181611193565b84529284019290840190600101610a3e565b5090979650505050505050565b600082601f830112610a80578081fd5b81356020610a90610a1b83611175565b8281528181019085830183850287018401881015610aac578586fd5b855b85811015610a6357813584529284019290840190600101610aae565b60008083601f840112610adb578182fd5b50813567ffffffffffffffff811115610af2578182fd5b6020830191508360208083028501011115610b0c57600080fd5b9250929050565b80358015158114610b2357600080fd5b919050565b6000608082840312156109c5578081fd5b600060808284031215610b4a578081fd5b6040516080810181811067ffffffffffffffff82111715610b6757fe5b6040529050808235610b7881611193565b8152610b8660208401610b13565b60208201526040830135610b9981611193565b6040820152610baa60608401610b13565b60608201525092915050565b600060208284031215610bc7578081fd5b8135610bd281611193565b9392505050565b60006020808385031215610beb578182fd5b825167ffffffffffffffff811115610c01578283fd5b8301601f81018513610c11578283fd5b8051610c1f610a1b82611175565b8181528381019083850185840285018601891015610c3b578687fd5b8694505b83851015610c5d578051835260019490940193918501918501610c3f565b50979650505050505050565b60008060208385031215610c7b578081fd5b823567ffffffffffffffff80821115610c92578283fd5b818501915085601f830112610ca5578283fd5b813581811115610cb3578384fd5b866020608083028501011115610cc7578384fd5b60209290920196919550909350505050565b6000806000806000806000806101a0898b031215610cf5578384fd5b883560028110610d03578485fd5b9750602089013567ffffffffffffffff80821115610d1f578586fd5b610d2b8c838d01610aca565b909950975060408b0135915080821115610d43578586fd5b610d4f8c838d016109fb565b9650610d5e8c60608d01610b39565b955060e08b0135915080821115610d73578485fd5b50610d808b828c01610a70565b9350506101008901359150610d998a6101208b01610b28565b90509295985092959890939650565b6000815180845260208085019450808401835b83811015610ded57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101610dbb565b509495945050505050565b6000815180845260208085019450808401835b83811015610ded57815187529582019590820190600101610e0b565b600082845282826020860137806020848601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011685010190509392505050565b73ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152506060810151151560608301525050565b600060208252610bd26020830184610df8565b602080825282518282018190526000919060409081850190868401855b82811015610f4c578151805160048110610ef957fe5b85528087015173ffffffffffffffffffffffffffffffffffffffff908116888701528682015187870152606080830151821690870152608091820151169085015260a09093019290850190600101610ee3565b5091979650505050505050565b600061012080830160028b10610f6b57fe5b8a8452602080850192909252889052610140808401918981028501909101908a845b8b811015611098577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec087850301855281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618e3603018112610fed578687fd5b8d01803585528381013584860152604080820135908601526060808201359086015260a0608080830135368490037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe101811261104757898afd5b8301803567ffffffffffffffff81111561105f578a8bfd5b80360385131561106d578a8bfd5b83838a0152611081848a01828a8501610e27565b998801999850505093850193505050600101610f8d565b50505083810360408501526110ad8189610da8565b9150506110bd6060840187610e6f565b82810360e08401526110cf8186610df8565b9150508261010083015298975050505050505050565b60208082526011908201527f475076323a206e6f742063726561746f72000000000000000000000000000000604082015260600190565b6020808252818101527f475076323a2063616e6e6f74207472616e73666572206e617469766520455448604082015260600190565b60405181810167ffffffffffffffff8111828210171561116d57fe5b604052919050565b600067ffffffffffffffff82111561118957fe5b5060209081020190565b73ffffffffffffffffffffffffffffffffffffffff811681146111b557600080fd5b5056fea2646970667358221220364a6941bea69620b7dc3a957d0ab4cbf3bfc459c7ad3924d220620aca9202fc64736f6c63430007060033

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

000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8

-----Decoded View---------------
Arg [0] : vault_ (address): 0xBA12222222228d8Ba445958a75a0704d566BF2C8

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8


Block Transaction Gas Used Reward
view all blocks validated

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

Validator Index Block Amount
View All Withdrawals

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