ETH Price: $2,527.10 (-0.36%)

Transaction Decoder

Block:
20134882 at Jun-20-2024 06:59:59 PM +UTC
Transaction Fee:
0.0007144314655802 ETH $1.81
Gas Used:
113,650 Gas / 6.286242548 Gwei

Emitted Events:

66 SafeToken.Approval( owner=[Receiver] Proxy, spender=0xC92E8bdf...16BFE0110, value=115792089237316195423570985008687907853269984665640564039457584007913129639935 )
67 GPv2Settlement.PreSignature( owner=[Receiver] Proxy, orderUid=0xCC8678C91471E4658F9DD5FEFD82ABB41A69C3D1E240B6040609E0AC23356BDC52B87A21A4AAA1E1FB2A1D6709FF8192137B0DFA66748230, signed=True )
68 Proxy.0x442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e( 0x442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e, 4dea4a1c97e4d485c8b67e0daeb4251c7d5a1b5c842e1e13ddfc1093f7ddf47d, 0000000000000000000000000000000000000000000000000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x52B87a21...2137b0dfA
0x5aFE3855...5e1c1eEEe
0x9008D19f...10560ab41
(CoW Protocol: GPv2Settlement)
0xC4e1f883...9bff47DB2
0.077677423968466659 Eth
Nonce: 379
0.076962992502886459 Eth
Nonce: 380
0.0007144314655802
(Flashbots: Builder 2)
2.292357338027008709 Eth2.292470988027008709 Eth0.00011365

Execution Trace

Proxy.6a761202( )
  • GnosisSafe.execTransaction( to=0x40A2aCCbd92BCA938b02010E17A5b8929b49130D, value=0, data=0x8D80FF0A00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000192005AFE3855358E112B5647B952709E6165E1C1EEEE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095EA7B3000000000000000000000000C92E8BDF79F0507F65A392B0AB4667716BFE0110FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF009008D19F58AABD9ED0D60971565AA8510560AB41000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A4EC6CB13F000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000038CC8678C91471E4658F9DD5FEFD82ABB41A69C3D1E240B6040609E0AC23356BDC52B87A21A4AAA1E1FB2A1D6709FF8192137B0DFA6674823000000000000000000000000000000000000000000000, operation=1, safeTxGas=0, baseGas=0, gasPrice=0, gasToken=0x0000000000000000000000000000000000000000, refundReceiver=0x0000000000000000000000000000000000000000, signatures=0xF775A5F74450640F10BCF7B2284956FD5092B1E246FF6AD6970CB7228B9F27467B41F56BB3045EB9CCD2704CD6027498656720E05763D12FB69AC9E74FF7B5B71B ) => ( success=True )
    • Null: 0x000...001.4dea4a1c( )
    • MultiSendCallOnly.multiSend( transactions=0x005AFE3855358E112B5647B952709E6165E1C1EEEE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095EA7B3000000000000000000000000C92E8BDF79F0507F65A392B0AB4667716BFE0110FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF009008D19F58AABD9ED0D60971565AA8510560AB41000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A4EC6CB13F000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000038CC8678C91471E4658F9DD5FEFD82ABB41A69C3D1E240B6040609E0AC23356BDC52B87A21A4AAA1E1FB2A1D6709FF8192137B0DFA667482300000000000000000 )
      • SafeToken.approve( spender=0xC92E8bdf79f0507f65a392b0ab4667716BFE0110, amount=115792089237316195423570985008687907853269984665640564039457584007913129639935 ) => ( True )
      • GPv2Settlement.setPreSignature( orderUid=0xCC8678C91471E4658F9DD5FEFD82ABB41A69C3D1E240B6040609E0AC23356BDC52B87A21A4AAA1E1FB2A1D6709FF8192137B0DFA66748230, signed=True )
        File 1 of 5: Proxy
        pragma solidity ^0.5.3;
        
        /// @title Proxy - Generic proxy contract allows to execute all transactions applying the code of a master contract.
        /// @author Stefan George - <[email protected]>
        /// @author Richard Meissner - <[email protected]>
        contract Proxy {
        
            // masterCopy always needs to be first declared variable, to ensure that it is at the same location in the contracts to which calls are delegated.
            // To reduce deployment costs this variable is internal and needs to be retrieved via `getStorageAt`
            address internal masterCopy;
        
            /// @dev Constructor function sets address of master copy contract.
            /// @param _masterCopy Master copy address.
            constructor(address _masterCopy)
                public
            {
                require(_masterCopy != address(0), "Invalid master copy address provided");
                masterCopy = _masterCopy;
            }
        
            /// @dev Fallback function forwards all transactions and returns all received return data.
            function ()
                external
                payable
            {
                // solium-disable-next-line security/no-inline-assembly
                assembly {
                    let masterCopy := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff)
                    // 0xa619486e == keccak("masterCopy()"). The value is right padded to 32-bytes with 0s
                    if eq(calldataload(0), 0xa619486e00000000000000000000000000000000000000000000000000000000) {
                        mstore(0, masterCopy)
                        return(0, 0x20)
                    }
                    calldatacopy(0, 0, calldatasize())
                    let success := delegatecall(gas, masterCopy, 0, calldatasize(), 0, 0)
                    returndatacopy(0, 0, returndatasize())
                    if eq(success, 0) { revert(0, returndatasize()) }
                    return(0, returndatasize())
                }
            }
        }

        File 2 of 5: SafeToken
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.8.0 <0.9.0;
        import "./vendor/@openzeppelin/contracts/access/Ownable.sol";
        import "./vendor/@openzeppelin/contracts/security/Pausable.sol";
        import "./vendor/@openzeppelin/contracts/token/ERC20/ERC20.sol";
        import "./TokenRescuer.sol";
        /// @title Safe Token contract
        /// @author Richard Meissner - @rmeissner
        contract SafeToken is ERC20, Pausable, Ownable, TokenRescuer {
            /// @dev Will mint 1 billion tokens to the owner and pause the contract
            constructor(address owner) ERC20("Safe Token", "SAFE") {
                // Transfer ownership immediately
                _transferOwnership(owner);
                // "ether" is used here to get 18 decimals
                _mint(owner, 1_000_000_000 ether);
                // Contract is paused by default
                // This has to be done after _mint, else minting will fail
                _pause();
            }
            /// @notice Unpauses all token transfers.
            /// @dev See {Pausable-_unpause}
            /// Requirements: caller must be the owner
            function unpause() public virtual onlyOwner {
                require(paused(), "SafeToken: token is not paused");
                _unpause();
            }
            /// @dev See {ERC20-_beforeTokenTransfer}
            /// Requirements: the contract must not be paused OR transfer must be initiated by owner
            /// @param from The account that is sending the tokens
            /// @param to The account that should receive the tokens
            /// @param amount Amount of tokens that should be transferred
            function _beforeTokenTransfer(
                address from,
                address to,
                uint256 amount
            ) internal virtual override {
                super._beforeTokenTransfer(from, to, amount);
                require(to != address(this), "SafeToken: cannot transfer tokens to token contract");
                // Token transfers are only possible if the contract is not paused
                // OR if triggered by the owner of the contract
                require(!paused() || owner() == _msgSender(), "SafeToken: token transfer while paused");
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.8.0 <0.9.0;
        import "./vendor/@openzeppelin/contracts/access/Ownable.sol";
        import "./vendor/@openzeppelin/contracts/token/ERC20/IERC20.sol";
        /// @title Token Rescuer contract
        /// @author Richard Meissner - @rmeissner
        contract TokenRescuer is Ownable {
            /// @param token Token that should be rescued
            /// @param beneficiary The account that should receive the tokens
            /// @param amount Amount of tokens that should be rescued
            function _beforeTokenRescue(
                IERC20 token,
                address beneficiary,
                uint256 amount
            ) internal virtual {}
            /// @notice Transfer all tokens with address `token` owned by this contract to `beneficiary`.
            /// @dev This can only be called by the owner of the contract
            /// @param token The token that should be rescued
            /// @param beneficiary The account that should receive the tokens.
            function rescueToken(IERC20 token, address beneficiary) external onlyOwner {
                uint256 balanceToRescue = token.balanceOf(address(this));
                require(balanceToRescue > 0, "TokenRescuer: No tokens to rescue");
                _beforeTokenRescue(token, beneficiary, balanceToRescue);
                require(token.transfer(beneficiary, balanceToRescue), "TokenRescuer: Could not rescue token");
            }
        }
        // SPDX-License-Identifier: MIT
        // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
        pragma solidity ^0.8.0;
        import "../utils/Context.sol";
        /**
         * @dev Contract module which provides a basic access control mechanism, where
         * there is an account (an owner) that can be granted exclusive access to
         * specific functions.
         *
         * By default, the owner account will be the one that deploys the contract. This
         * can later be changed with {transferOwnership}.
         *
         * This module is used through inheritance. It will make available the modifier
         * `onlyOwner`, which can be applied to your functions to restrict their use to
         * the owner.
         */
        abstract contract Ownable is Context {
            address private _owner;
            event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
            /**
             * @dev Initializes the contract setting the deployer as the initial owner.
             */
            constructor() {
                _transferOwnership(_msgSender());
            }
            /**
             * @dev Returns the address of the current owner.
             */
            function owner() public view virtual returns (address) {
                return _owner;
            }
            /**
             * @dev Throws if called by any account other than the owner.
             */
            modifier onlyOwner() {
                require(owner() == _msgSender(), "Ownable: caller is not the owner");
                _;
            }
            /**
             * @dev Leaves the contract without owner. It will not be possible to call
             * `onlyOwner` functions anymore. Can only be called by the current owner.
             *
             * NOTE: Renouncing ownership will leave the contract without an owner,
             * thereby removing any functionality that is only available to the owner.
             */
            function renounceOwnership() public virtual onlyOwner {
                _transferOwnership(address(0));
            }
            /**
             * @dev Transfers ownership of the contract to a new account (`newOwner`).
             * Can only be called by the current owner.
             */
            function transferOwnership(address newOwner) public virtual onlyOwner {
                require(newOwner != address(0), "Ownable: new owner is the zero address");
                _transferOwnership(newOwner);
            }
            /**
             * @dev Transfers ownership of the contract to a new account (`newOwner`).
             * Internal function without access restriction.
             */
            function _transferOwnership(address newOwner) internal virtual {
                address oldOwner = _owner;
                _owner = newOwner;
                emit OwnershipTransferred(oldOwner, newOwner);
            }
        }
        // SPDX-License-Identifier: MIT
        // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)
        pragma solidity ^0.8.0;
        import "../utils/Context.sol";
        /**
         * @dev Contract module which allows children to implement an emergency stop
         * mechanism that can be triggered by an authorized account.
         *
         * This module is used through inheritance. It will make available the
         * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
         * the functions of your contract. Note that they will not be pausable by
         * simply including this module, only once the modifiers are put in place.
         */
        abstract contract Pausable is Context {
            /**
             * @dev Emitted when the pause is triggered by `account`.
             */
            event Paused(address account);
            /**
             * @dev Emitted when the pause is lifted by `account`.
             */
            event Unpaused(address account);
            bool private _paused;
            /**
             * @dev Initializes the contract in unpaused state.
             */
            constructor() {
                _paused = false;
            }
            /**
             * @dev Returns true if the contract is paused, and false otherwise.
             */
            function paused() public view virtual returns (bool) {
                return _paused;
            }
            /**
             * @dev Modifier to make a function callable only when the contract is not paused.
             *
             * Requirements:
             *
             * - The contract must not be paused.
             */
            modifier whenNotPaused() {
                require(!paused(), "Pausable: paused");
                _;
            }
            /**
             * @dev Modifier to make a function callable only when the contract is paused.
             *
             * Requirements:
             *
             * - The contract must be paused.
             */
            modifier whenPaused() {
                require(paused(), "Pausable: not paused");
                _;
            }
            /**
             * @dev Triggers stopped state.
             *
             * Requirements:
             *
             * - The contract must not be paused.
             */
            function _pause() internal virtual whenNotPaused {
                _paused = true;
                emit Paused(_msgSender());
            }
            /**
             * @dev Returns to normal state.
             *
             * Requirements:
             *
             * - The contract must be paused.
             */
            function _unpause() internal virtual whenPaused {
                _paused = false;
                emit Unpaused(_msgSender());
            }
        }
        // SPDX-License-Identifier: MIT
        // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)
        pragma solidity ^0.8.0;
        import "./IERC20.sol";
        import "./extensions/IERC20Metadata.sol";
        import "../../utils/Context.sol";
        /**
         * @dev Implementation of the {IERC20} interface.
         *
         * This implementation is agnostic to the way tokens are created. This means
         * that a supply mechanism has to be added in a derived contract using {_mint}.
         * For a generic mechanism see {ERC20PresetMinterPauser}.
         *
         * TIP: For a detailed writeup see our guide
         * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
         * to implement supply mechanisms].
         *
         * We have followed general OpenZeppelin Contracts guidelines: functions revert
         * instead returning `false` on failure. This behavior is nonetheless
         * conventional and does not conflict with the expectations of ERC20
         * applications.
         *
         * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
         * This allows applications to reconstruct the allowance for all accounts just
         * by listening to said events. Other implementations of the EIP may not emit
         * these events, as it isn't required by the specification.
         *
         * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
         * functions have been added to mitigate the well-known issues around setting
         * allowances. See {IERC20-approve}.
         */
        contract ERC20 is Context, IERC20, IERC20Metadata {
            mapping(address => uint256) private _balances;
            mapping(address => mapping(address => uint256)) private _allowances;
            uint256 private _totalSupply;
            string private _name;
            string private _symbol;
            /**
             * @dev Sets the values for {name} and {symbol}.
             *
             * The default value of {decimals} is 18. To select a different value for
             * {decimals} you should overload it.
             *
             * All two of these values are immutable: they can only be set once during
             * construction.
             */
            constructor(string memory name_, string memory symbol_) {
                _name = name_;
                _symbol = symbol_;
            }
            /**
             * @dev Returns the name of the token.
             */
            function name() public view virtual override returns (string memory) {
                return _name;
            }
            /**
             * @dev Returns the symbol of the token, usually a shorter version of the
             * name.
             */
            function symbol() public view virtual override returns (string memory) {
                return _symbol;
            }
            /**
             * @dev Returns the number of decimals used to get its user representation.
             * For example, if `decimals` equals `2`, a balance of `505` tokens should
             * be displayed to a user as `5.05` (`505 / 10 ** 2`).
             *
             * Tokens usually opt for a value of 18, imitating the relationship between
             * Ether and Wei. This is the value {ERC20} uses, unless this function is
             * overridden;
             *
             * NOTE: This information is only used for _display_ purposes: it in
             * no way affects any of the arithmetic of the contract, including
             * {IERC20-balanceOf} and {IERC20-transfer}.
             */
            function decimals() public view virtual override returns (uint8) {
                return 18;
            }
            /**
             * @dev See {IERC20-totalSupply}.
             */
            function totalSupply() public view virtual override returns (uint256) {
                return _totalSupply;
            }
            /**
             * @dev See {IERC20-balanceOf}.
             */
            function balanceOf(address account) public view virtual override returns (uint256) {
                return _balances[account];
            }
            /**
             * @dev See {IERC20-transfer}.
             *
             * Requirements:
             *
             * - `to` cannot be the zero address.
             * - the caller must have a balance of at least `amount`.
             */
            function transfer(address to, uint256 amount) public virtual override returns (bool) {
                address owner = _msgSender();
                _transfer(owner, to, amount);
                return true;
            }
            /**
             * @dev See {IERC20-allowance}.
             */
            function allowance(address owner, address spender) public view virtual override returns (uint256) {
                return _allowances[owner][spender];
            }
            /**
             * @dev See {IERC20-approve}.
             *
             * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
             * `transferFrom`. This is semantically equivalent to an infinite approval.
             *
             * Requirements:
             *
             * - `spender` cannot be the zero address.
             */
            function approve(address spender, uint256 amount) public virtual override returns (bool) {
                address owner = _msgSender();
                _approve(owner, spender, amount);
                return true;
            }
            /**
             * @dev See {IERC20-transferFrom}.
             *
             * Emits an {Approval} event indicating the updated allowance. This is not
             * required by the EIP. See the note at the beginning of {ERC20}.
             *
             * NOTE: Does not update the allowance if the current allowance
             * is the maximum `uint256`.
             *
             * Requirements:
             *
             * - `from` and `to` cannot be the zero address.
             * - `from` must have a balance of at least `amount`.
             * - the caller must have allowance for ``from``'s tokens of at least
             * `amount`.
             */
            function transferFrom(
                address from,
                address to,
                uint256 amount
            ) public virtual override returns (bool) {
                address spender = _msgSender();
                _spendAllowance(from, spender, amount);
                _transfer(from, to, amount);
                return true;
            }
            /**
             * @dev Atomically increases the allowance granted to `spender` by the caller.
             *
             * This is an alternative to {approve} that can be used as a mitigation for
             * problems described in {IERC20-approve}.
             *
             * Emits an {Approval} event indicating the updated allowance.
             *
             * Requirements:
             *
             * - `spender` cannot be the zero address.
             */
            function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
                address owner = _msgSender();
                _approve(owner, spender, _allowances[owner][spender] + addedValue);
                return true;
            }
            /**
             * @dev Atomically decreases the allowance granted to `spender` by the caller.
             *
             * This is an alternative to {approve} that can be used as a mitigation for
             * problems described in {IERC20-approve}.
             *
             * Emits an {Approval} event indicating the updated allowance.
             *
             * Requirements:
             *
             * - `spender` cannot be the zero address.
             * - `spender` must have allowance for the caller of at least
             * `subtractedValue`.
             */
            function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
                address owner = _msgSender();
                uint256 currentAllowance = _allowances[owner][spender];
                require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
                unchecked {
                    _approve(owner, spender, currentAllowance - subtractedValue);
                }
                return true;
            }
            /**
             * @dev Moves `amount` of tokens from `sender` to `recipient`.
             *
             * This internal function is equivalent to {transfer}, and can be used to
             * e.g. implement automatic token fees, slashing mechanisms, etc.
             *
             * Emits a {Transfer} event.
             *
             * Requirements:
             *
             * - `from` cannot be the zero address.
             * - `to` cannot be the zero address.
             * - `from` must have a balance of at least `amount`.
             */
            function _transfer(
                address from,
                address to,
                uint256 amount
            ) internal virtual {
                require(from != address(0), "ERC20: transfer from the zero address");
                require(to != address(0), "ERC20: transfer to the zero address");
                _beforeTokenTransfer(from, to, amount);
                uint256 fromBalance = _balances[from];
                require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
                unchecked {
                    _balances[from] = fromBalance - amount;
                }
                _balances[to] += amount;
                emit Transfer(from, to, amount);
                _afterTokenTransfer(from, to, amount);
            }
            /** @dev Creates `amount` tokens and assigns them to `account`, increasing
             * the total supply.
             *
             * Emits a {Transfer} event with `from` set to the zero address.
             *
             * Requirements:
             *
             * - `account` cannot be the zero address.
             */
            function _mint(address account, uint256 amount) internal virtual {
                require(account != address(0), "ERC20: mint to the zero address");
                _beforeTokenTransfer(address(0), account, amount);
                _totalSupply += amount;
                _balances[account] += amount;
                emit Transfer(address(0), account, amount);
                _afterTokenTransfer(address(0), account, amount);
            }
            /**
             * @dev Destroys `amount` tokens from `account`, reducing the
             * total supply.
             *
             * Emits a {Transfer} event with `to` set to the zero address.
             *
             * Requirements:
             *
             * - `account` cannot be the zero address.
             * - `account` must have at least `amount` tokens.
             */
            function _burn(address account, uint256 amount) internal virtual {
                require(account != address(0), "ERC20: burn from the zero address");
                _beforeTokenTransfer(account, address(0), amount);
                uint256 accountBalance = _balances[account];
                require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
                unchecked {
                    _balances[account] = accountBalance - amount;
                }
                _totalSupply -= amount;
                emit Transfer(account, address(0), amount);
                _afterTokenTransfer(account, address(0), amount);
            }
            /**
             * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
             *
             * This internal function is equivalent to `approve`, and can be used to
             * e.g. set automatic allowances for certain subsystems, etc.
             *
             * Emits an {Approval} event.
             *
             * Requirements:
             *
             * - `owner` cannot be the zero address.
             * - `spender` cannot be the zero address.
             */
            function _approve(
                address owner,
                address spender,
                uint256 amount
            ) internal virtual {
                require(owner != address(0), "ERC20: approve from the zero address");
                require(spender != address(0), "ERC20: approve to the zero address");
                _allowances[owner][spender] = amount;
                emit Approval(owner, spender, amount);
            }
            /**
             * @dev Spend `amount` form the allowance of `owner` toward `spender`.
             *
             * Does not update the allowance amount in case of infinite allowance.
             * Revert if not enough allowance is available.
             *
             * Might emit an {Approval} event.
             */
            function _spendAllowance(
                address owner,
                address spender,
                uint256 amount
            ) internal virtual {
                uint256 currentAllowance = allowance(owner, spender);
                if (currentAllowance != type(uint256).max) {
                    require(currentAllowance >= amount, "ERC20: insufficient allowance");
                    unchecked {
                        _approve(owner, spender, currentAllowance - amount);
                    }
                }
            }
            /**
             * @dev Hook that is called before any transfer of tokens. This includes
             * minting and burning.
             *
             * Calling conditions:
             *
             * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
             * will be transferred to `to`.
             * - when `from` is zero, `amount` tokens will be minted for `to`.
             * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
             * - `from` and `to` are never both zero.
             *
             * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
             */
            function _beforeTokenTransfer(
                address from,
                address to,
                uint256 amount
            ) internal virtual {}
            /**
             * @dev Hook that is called after any transfer of tokens. This includes
             * minting and burning.
             *
             * Calling conditions:
             *
             * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
             * has been transferred to `to`.
             * - when `from` is zero, `amount` tokens have been minted for `to`.
             * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
             * - `from` and `to` are never both zero.
             *
             * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
             */
            function _afterTokenTransfer(
                address from,
                address to,
                uint256 amount
            ) internal virtual {}
        }
        // SPDX-License-Identifier: MIT
        // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)
        pragma solidity ^0.8.0;
        /**
         * @dev Interface of the ERC20 standard as defined in the EIP.
         */
        interface IERC20 {
            /**
             * @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);
            /**
             * @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);
        }
        // SPDX-License-Identifier: MIT
        // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
        pragma solidity ^0.8.0;
        import "../IERC20.sol";
        /**
         * @dev Interface for the optional metadata functions from the ERC20 standard.
         *
         * _Available since v4.1._
         */
        interface IERC20Metadata is IERC20 {
            /**
             * @dev Returns the name of the token.
             */
            function name() external view returns (string memory);
            /**
             * @dev Returns the symbol of the token.
             */
            function symbol() external view returns (string memory);
            /**
             * @dev Returns the decimals places of the token.
             */
            function decimals() external view returns (uint8);
        }
        // SPDX-License-Identifier: MIT
        // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
        pragma solidity ^0.8.0;
        /**
         * @dev Provides information about the current execution context, including the
         * sender of the transaction and its data. While these are generally available
         * via msg.sender and msg.data, they should not be accessed in such a direct
         * manner, since when dealing with meta-transactions the account sending and
         * paying for execution may not be the actual sender (as far as an application
         * is concerned).
         *
         * This contract is only required for intermediate, library-like contracts.
         */
        abstract contract Context {
            function _msgSender() internal view virtual returns (address) {
                return msg.sender;
            }
            function _msgData() internal view virtual returns (bytes calldata) {
                return msg.data;
            }
        }
        

        File 3 of 5: GPv2Settlement
        // SPDX-License-Identifier: LGPL-3.0-or-later
        pragma solidity ^0.7.6;
        pragma abicoder v2;
        import "./GPv2VaultRelayer.sol";
        import "./interfaces/GPv2Authentication.sol";
        import "./interfaces/IERC20.sol";
        import "./interfaces/IVault.sol";
        import "./libraries/GPv2Interaction.sol";
        import "./libraries/GPv2Order.sol";
        import "./libraries/GPv2Trade.sol";
        import "./libraries/GPv2Transfer.sol";
        import "./libraries/SafeCast.sol";
        import "./libraries/SafeMath.sol";
        import "./mixins/GPv2Signing.sol";
        import "./mixins/ReentrancyGuard.sol";
        import "./mixins/StorageAccessible.sol";
        /// @title Gnosis Protocol v2 Settlement Contract
        /// @author Gnosis Developers
        contract GPv2Settlement is GPv2Signing, ReentrancyGuard, StorageAccessible {
            using GPv2Order for bytes;
            using GPv2Transfer for IVault;
            using SafeCast for int256;
            using SafeCast for uint256;
            using SafeMath for uint256;
            /// @dev The authenticator is used to determine who can call the settle function.
            /// That is, only authorised solvers have the ability to invoke settlements.
            /// Any valid authenticator implements an isSolver method called by the onlySolver
            /// modifier below.
            GPv2Authentication public immutable authenticator;
            /// @dev The Balancer Vault the protocol uses for managing user funds.
            IVault public immutable vault;
            /// @dev The Balancer Vault relayer which can interact on behalf of users.
            /// This contract is created during deployment
            GPv2VaultRelayer public immutable vaultRelayer;
            /// @dev Map each user order by UID to the amount that has been filled so
            /// far. If this amount is larger than or equal to the amount traded in the
            /// order (amount sold for sell orders, amount bought for buy orders) then
            /// the order cannot be traded anymore. If the order is fill or kill, then
            /// this value is only used to determine whether the order has already been
            /// executed.
            mapping(bytes => uint256) public filledAmount;
            /// @dev Event emitted for each executed trade.
            event Trade(
                address indexed owner,
                IERC20 sellToken,
                IERC20 buyToken,
                uint256 sellAmount,
                uint256 buyAmount,
                uint256 feeAmount,
                bytes orderUid
            );
            /// @dev Event emitted for each executed interaction.
            ///
            /// For gas effeciency, only the interaction calldata selector (first 4
            /// bytes) is included in the event. For interactions without calldata or
            /// whose calldata is shorter than 4 bytes, the selector will be `0`.
            event Interaction(address indexed target, uint256 value, bytes4 selector);
            /// @dev Event emitted when a settlement complets
            event Settlement(address indexed solver);
            /// @dev Event emitted when an order is invalidated.
            event OrderInvalidated(address indexed owner, bytes orderUid);
            constructor(GPv2Authentication authenticator_, IVault vault_) {
                authenticator = authenticator_;
                vault = vault_;
                vaultRelayer = new GPv2VaultRelayer(vault_);
            }
            // solhint-disable-next-line no-empty-blocks
            receive() external payable {
                // NOTE: Include an empty receive function so that the settlement
                // contract can receive Ether from contract interactions.
            }
            /// @dev This modifier is called by settle function to block any non-listed
            /// senders from settling batches.
            modifier onlySolver {
                require(authenticator.isSolver(msg.sender), "GPv2: not a solver");
                _;
            }
            /// @dev Modifier to ensure that an external function is only callable as a
            /// settlement interaction.
            modifier onlyInteraction {
                require(address(this) == msg.sender, "GPv2: not an interaction");
                _;
            }
            /// @dev Settle the specified orders at a clearing price. Note that it is
            /// the responsibility of the caller to ensure that all GPv2 invariants are
            /// upheld for the input settlement, otherwise this call will revert.
            /// Namely:
            /// - All orders are valid and signed
            /// - Accounts have sufficient balance and approval.
            /// - Settlement contract has sufficient balance to execute trades. Note
            ///   this implies that the accumulated fees held in the contract can also
            ///   be used for settlement. This is OK since:
            ///   - Solvers need to be authorized
            ///   - Misbehaving solvers will be slashed for abusing accumulated fees for
            ///     settlement
            ///   - Critically, user orders are entirely protected
            ///
            /// @param tokens An array of ERC20 tokens to be traded in the settlement.
            /// Trades encode tokens as indices into this array.
            /// @param clearingPrices An array of clearing prices where the `i`-th price
            /// is for the `i`-th token in the [`tokens`] array.
            /// @param trades Trades for signed orders.
            /// @param interactions Smart contract interactions split into three
            /// separate lists to be run before the settlement, during the settlement
            /// and after the settlement respectively.
            function settle(
                IERC20[] calldata tokens,
                uint256[] calldata clearingPrices,
                GPv2Trade.Data[] calldata trades,
                GPv2Interaction.Data[][3] calldata interactions
            ) external nonReentrant onlySolver {
                executeInteractions(interactions[0]);
                (
                    GPv2Transfer.Data[] memory inTransfers,
                    GPv2Transfer.Data[] memory outTransfers
                ) = computeTradeExecutions(tokens, clearingPrices, trades);
                vaultRelayer.transferFromAccounts(inTransfers);
                executeInteractions(interactions[1]);
                vault.transferToAccounts(outTransfers);
                executeInteractions(interactions[2]);
                emit Settlement(msg.sender);
            }
            /// @dev Settle an order directly against Balancer V2 pools.
            ///
            /// @param swaps The Balancer V2 swap steps to use for trading.
            /// @param tokens An array of ERC20 tokens to be traded in the settlement.
            /// Swaps and the trade encode tokens as indices into this array.
            /// @param trade The trade to match directly against Balancer liquidity. The
            /// order will always be fully executed, so the trade's `executedAmount`
            /// field is used to represent a swap limit amount.
            function swap(
                IVault.BatchSwapStep[] calldata swaps,
                IERC20[] calldata tokens,
                GPv2Trade.Data calldata trade
            ) external nonReentrant onlySolver {
                RecoveredOrder memory recoveredOrder = allocateRecoveredOrder();
                GPv2Order.Data memory order = recoveredOrder.data;
                recoverOrderFromTrade(recoveredOrder, tokens, trade);
                IVault.SwapKind kind =
                    order.kind == GPv2Order.KIND_SELL
                        ? IVault.SwapKind.GIVEN_IN
                        : IVault.SwapKind.GIVEN_OUT;
                IVault.FundManagement memory funds;
                funds.sender = recoveredOrder.owner;
                funds.fromInternalBalance =
                    order.sellTokenBalance == GPv2Order.BALANCE_INTERNAL;
                funds.recipient = payable(recoveredOrder.receiver);
                funds.toInternalBalance =
                    order.buyTokenBalance == GPv2Order.BALANCE_INTERNAL;
                int256[] memory limits = new int256[](tokens.length);
                uint256 limitAmount = trade.executedAmount;
                // NOTE: Array allocation initializes elements to 0, so we only need to
                // set the limits we care about. This ensures that the swap will respect
                // the order's limit price.
                if (order.kind == GPv2Order.KIND_SELL) {
                    require(limitAmount >= order.buyAmount, "GPv2: limit too low");
                    limits[trade.sellTokenIndex] = order.sellAmount.toInt256();
                    limits[trade.buyTokenIndex] = -limitAmount.toInt256();
                } else {
                    require(limitAmount <= order.sellAmount, "GPv2: limit too high");
                    limits[trade.sellTokenIndex] = limitAmount.toInt256();
                    limits[trade.buyTokenIndex] = -order.buyAmount.toInt256();
                }
                GPv2Transfer.Data memory feeTransfer;
                feeTransfer.account = recoveredOrder.owner;
                feeTransfer.token = order.sellToken;
                feeTransfer.amount = order.feeAmount;
                feeTransfer.balance = order.sellTokenBalance;
                int256[] memory tokenDeltas =
                    vaultRelayer.batchSwapWithFee(
                        kind,
                        swaps,
                        tokens,
                        funds,
                        limits,
                        // NOTE: Specify a deadline to ensure that an expire order
                        // cannot be used to trade.
                        order.validTo,
                        feeTransfer
                    );
                bytes memory orderUid = recoveredOrder.uid;
                uint256 executedSellAmount =
                    tokenDeltas[trade.sellTokenIndex].toUint256();
                uint256 executedBuyAmount =
                    (-tokenDeltas[trade.buyTokenIndex]).toUint256();
                // NOTE: Check that the orders were completely filled and update their
                // filled amounts to avoid replaying them. The limit price and order
                // validity have already been verified when executing the swap through
                // the `limit` and `deadline` parameters.
                require(filledAmount[orderUid] == 0, "GPv2: order filled");
                if (order.kind == GPv2Order.KIND_SELL) {
                    require(
                        executedSellAmount == order.sellAmount,
                        "GPv2: sell amount not respected"
                    );
                    filledAmount[orderUid] = order.sellAmount;
                } else {
                    require(
                        executedBuyAmount == order.buyAmount,
                        "GPv2: buy amount not respected"
                    );
                    filledAmount[orderUid] = order.buyAmount;
                }
                emit Trade(
                    recoveredOrder.owner,
                    order.sellToken,
                    order.buyToken,
                    executedSellAmount,
                    executedBuyAmount,
                    order.feeAmount,
                    orderUid
                );
                emit Settlement(msg.sender);
            }
            /// @dev Invalidate onchain an order that has been signed offline.
            ///
            /// @param orderUid The unique identifier of the order that is to be made
            /// invalid after calling this function. The user that created the order
            /// must be the the sender of this message. See [`extractOrderUidParams`]
            /// for details on orderUid.
            function invalidateOrder(bytes calldata orderUid) external {
                (, address owner, ) = orderUid.extractOrderUidParams();
                require(owner == msg.sender, "GPv2: caller does not own order");
                filledAmount[orderUid] = uint256(-1);
                emit OrderInvalidated(owner, orderUid);
            }
            /// @dev Free storage from the filled amounts of **expired** orders to claim
            /// a gas refund. This method can only be called as an interaction.
            ///
            /// @param orderUids The unique identifiers of the expired order to free
            /// storage for.
            function freeFilledAmountStorage(bytes[] calldata orderUids)
                external
                onlyInteraction
            {
                freeOrderStorage(filledAmount, orderUids);
            }
            /// @dev Free storage from the pre signatures of **expired** orders to claim
            /// a gas refund. This method can only be called as an interaction.
            ///
            /// @param orderUids The unique identifiers of the expired order to free
            /// storage for.
            function freePreSignatureStorage(bytes[] calldata orderUids)
                external
                onlyInteraction
            {
                freeOrderStorage(preSignature, orderUids);
            }
            /// @dev Process all trades one at a time returning the computed net in and
            /// out transfers for the trades.
            ///
            /// This method reverts if processing of any single trade fails. See
            /// [`computeTradeExecution`] for more details.
            ///
            /// @param tokens An array of ERC20 tokens to be traded in the settlement.
            /// @param clearingPrices An array of token clearing prices.
            /// @param trades Trades for signed orders.
            /// @return inTransfers Array of in transfers of executed sell amounts.
            /// @return outTransfers Array of out transfers of executed buy amounts.
            function computeTradeExecutions(
                IERC20[] calldata tokens,
                uint256[] calldata clearingPrices,
                GPv2Trade.Data[] calldata trades
            )
                internal
                returns (
                    GPv2Transfer.Data[] memory inTransfers,
                    GPv2Transfer.Data[] memory outTransfers
                )
            {
                RecoveredOrder memory recoveredOrder = allocateRecoveredOrder();
                inTransfers = new GPv2Transfer.Data[](trades.length);
                outTransfers = new GPv2Transfer.Data[](trades.length);
                for (uint256 i = 0; i < trades.length; i++) {
                    GPv2Trade.Data calldata trade = trades[i];
                    recoverOrderFromTrade(recoveredOrder, tokens, trade);
                    computeTradeExecution(
                        recoveredOrder,
                        clearingPrices[trade.sellTokenIndex],
                        clearingPrices[trade.buyTokenIndex],
                        trade.executedAmount,
                        inTransfers[i],
                        outTransfers[i]
                    );
                }
            }
            /// @dev Compute the in and out transfer amounts for a single trade.
            /// This function reverts if:
            /// - The order has expired
            /// - The order's limit price is not respected
            /// - The order gets over-filled
            /// - The fee discount is larger than the executed fee
            ///
            /// @param recoveredOrder The recovered order to process.
            /// @param sellPrice The price of the order's sell token.
            /// @param buyPrice The price of the order's buy token.
            /// @param executedAmount The portion of the order to execute. This will be
            /// ignored for fill-or-kill orders.
            /// @param inTransfer Memory location for computed executed sell amount
            /// transfer.
            /// @param outTransfer Memory location for computed executed buy amount
            /// transfer.
            function computeTradeExecution(
                RecoveredOrder memory recoveredOrder,
                uint256 sellPrice,
                uint256 buyPrice,
                uint256 executedAmount,
                GPv2Transfer.Data memory inTransfer,
                GPv2Transfer.Data memory outTransfer
            ) internal {
                GPv2Order.Data memory order = recoveredOrder.data;
                bytes memory orderUid = recoveredOrder.uid;
                // solhint-disable-next-line not-rely-on-time
                require(order.validTo >= block.timestamp, "GPv2: order expired");
                // NOTE: The following computation is derived from the equation:
                // ```
                // amount_x * price_x = amount_y * price_y
                // ```
                // Intuitively, if a chocolate bar is 0,50€ and a beer is 4€, 1 beer
                // is roughly worth 8 chocolate bars (`1 * 4 = 8 * 0.5`). From this
                // equation, we can derive:
                // - The limit price for selling `x` and buying `y` is respected iff
                // ```
                // limit_x * price_x >= limit_y * price_y
                // ```
                // - The executed amount of token `y` given some amount of `x` and
                //   clearing prices is:
                // ```
                // amount_y = amount_x * price_x / price_y
                // ```
                require(
                    order.sellAmount.mul(sellPrice) >= order.buyAmount.mul(buyPrice),
                    "GPv2: limit price not respected"
                );
                uint256 executedSellAmount;
                uint256 executedBuyAmount;
                uint256 executedFeeAmount;
                uint256 currentFilledAmount;
                if (order.kind == GPv2Order.KIND_SELL) {
                    if (order.partiallyFillable) {
                        executedSellAmount = executedAmount;
                        executedFeeAmount = order.feeAmount.mul(executedSellAmount).div(
                            order.sellAmount
                        );
                    } else {
                        executedSellAmount = order.sellAmount;
                        executedFeeAmount = order.feeAmount;
                    }
                    executedBuyAmount = executedSellAmount.mul(sellPrice).ceilDiv(
                        buyPrice
                    );
                    currentFilledAmount = filledAmount[orderUid].add(
                        executedSellAmount
                    );
                    require(
                        currentFilledAmount <= order.sellAmount,
                        "GPv2: order filled"
                    );
                } else {
                    if (order.partiallyFillable) {
                        executedBuyAmount = executedAmount;
                        executedFeeAmount = order.feeAmount.mul(executedBuyAmount).div(
                            order.buyAmount
                        );
                    } else {
                        executedBuyAmount = order.buyAmount;
                        executedFeeAmount = order.feeAmount;
                    }
                    executedSellAmount = executedBuyAmount.mul(buyPrice).div(sellPrice);
                    currentFilledAmount = filledAmount[orderUid].add(executedBuyAmount);
                    require(
                        currentFilledAmount <= order.buyAmount,
                        "GPv2: order filled"
                    );
                }
                executedSellAmount = executedSellAmount.add(executedFeeAmount);
                filledAmount[orderUid] = currentFilledAmount;
                emit Trade(
                    recoveredOrder.owner,
                    order.sellToken,
                    order.buyToken,
                    executedSellAmount,
                    executedBuyAmount,
                    executedFeeAmount,
                    orderUid
                );
                inTransfer.account = recoveredOrder.owner;
                inTransfer.token = order.sellToken;
                inTransfer.amount = executedSellAmount;
                inTransfer.balance = order.sellTokenBalance;
                outTransfer.account = recoveredOrder.receiver;
                outTransfer.token = order.buyToken;
                outTransfer.amount = executedBuyAmount;
                outTransfer.balance = order.buyTokenBalance;
            }
            /// @dev Execute a list of arbitrary contract calls from this contract.
            /// @param interactions The list of interactions to execute.
            function executeInteractions(GPv2Interaction.Data[] calldata interactions)
                internal
            {
                for (uint256 i; i < interactions.length; i++) {
                    GPv2Interaction.Data calldata interaction = interactions[i];
                    // To prevent possible attack on user funds, we explicitly disable
                    // any interactions with the vault relayer contract.
                    require(
                        interaction.target != address(vaultRelayer),
                        "GPv2: forbidden interaction"
                    );
                    GPv2Interaction.execute(interaction);
                    emit Interaction(
                        interaction.target,
                        interaction.value,
                        GPv2Interaction.selector(interaction)
                    );
                }
            }
            /// @dev Claims refund for the specified storage and order UIDs.
            ///
            /// This method reverts if any of the orders are still valid.
            ///
            /// @param orderUids Order refund data for freeing storage.
            /// @param orderStorage Order storage mapped on a UID.
            function freeOrderStorage(
                mapping(bytes => uint256) storage orderStorage,
                bytes[] calldata orderUids
            ) internal {
                for (uint256 i = 0; i < orderUids.length; i++) {
                    bytes calldata orderUid = orderUids[i];
                    (, , uint32 validTo) = orderUid.extractOrderUidParams();
                    // solhint-disable-next-line not-rely-on-time
                    require(validTo < block.timestamp, "GPv2: order still valid");
                    orderStorage[orderUid] = 0;
                }
            }
        }
        // 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);
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-or-later
        pragma solidity ^0.7.6;
        /// @title Gnosis Protocol v2 Authentication Interface
        /// @author Gnosis Developers
        interface GPv2Authentication {
            /// @dev determines whether the provided address is an authenticated solver.
            /// @param prospectiveSolver the address of prospective solver.
            /// @return true when prospectiveSolver is an authenticated solver, otherwise false.
            function isSolver(address prospectiveSolver) external view returns (bool);
        }
        // SPDX-License-Identifier: LGPL-3.0-or-later
        pragma solidity ^0.7.6;
        library GPv2EIP1271 {
            /// @dev Value returned by a call to `isValidSignature` if the signature
            /// was verified successfully. The value is defined in EIP-1271 as:
            /// bytes4(keccak256("isValidSignature(bytes32,bytes)"))
            bytes4 internal constant MAGICVALUE = 0x1626ba7e;
        }
        /// @title EIP1271 Interface
        /// @dev Standardized interface for an implementation of smart contract
        /// signatures as described in EIP-1271. The code that follows is identical to
        /// the code in the standard with the exception of formatting and syntax
        /// changes to adapt the code to our Solidity version.
        interface EIP1271Verifier {
            /// @dev Should return whether the signature provided is valid for the
            /// provided data
            /// @param _hash      Hash of the data to be signed
            /// @param _signature Signature byte array associated with _data
            ///
            /// MUST return the bytes4 magic value 0x1626ba7e when function passes.
            /// MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for
            /// solc > 0.5)
            /// MUST allow external calls
            ///
            function isValidSignature(bytes32 _hash, bytes memory _signature)
                external
                view
                returns (bytes4 magicValue);
        }
        // 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
            );
        }
        // 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;
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-or-later
        pragma solidity ^0.7.6;
        /// @title Gnosis Protocol v2 Interaction Library
        /// @author Gnosis Developers
        library GPv2Interaction {
            /// @dev Interaction data for performing arbitrary contract interactions.
            /// Submitted to [`GPv2Settlement.settle`] for code execution.
            struct Data {
                address target;
                uint256 value;
                bytes callData;
            }
            /// @dev Execute an arbitrary contract interaction.
            ///
            /// @param interaction Interaction data.
            function execute(Data calldata interaction) internal {
                address target = interaction.target;
                uint256 value = interaction.value;
                bytes calldata callData = interaction.callData;
                // NOTE: Use assembly to call the interaction instead of a low level
                // call for two reasons:
                // - We don't want to copy the return data, since we discard it for
                // interactions.
                // - Solidity will under certain conditions generate code to copy input
                // calldata twice to memory (the second being a "memcopy loop").
                // <https://github.com/gnosis/gp-v2-contracts/pull/417#issuecomment-775091258>
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let freeMemoryPointer := mload(0x40)
                    calldatacopy(freeMemoryPointer, callData.offset, callData.length)
                    if iszero(
                        call(
                            gas(),
                            target,
                            value,
                            freeMemoryPointer,
                            callData.length,
                            0,
                            0
                        )
                    ) {
                        returndatacopy(0, 0, returndatasize())
                        revert(0, returndatasize())
                    }
                }
            }
            /// @dev Extracts the Solidity ABI selector for the specified interaction.
            ///
            /// @param interaction Interaction data.
            /// @return result The 4 byte function selector of the call encoded in
            /// this interaction.
            function selector(Data calldata interaction)
                internal
                pure
                returns (bytes4 result)
            {
                bytes calldata callData = interaction.callData;
                if (callData.length >= 4) {
                    // NOTE: Read the first word of the interaction's calldata. The
                    // value does not need to be shifted since `bytesN` values are left
                    // aligned, and the value does not need to be masked since masking
                    // occurs when the value is accessed and not stored:
                    // <https://docs.soliditylang.org/en/v0.7.6/abi-spec.html#encoding-of-indexed-event-parameters>
                    // <https://docs.soliditylang.org/en/v0.7.6/assembly.html#access-to-external-variables-functions-and-libraries>
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        result := calldataload(callData.offset)
                    }
                }
            }
        }
        // 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 10 fields, and
                // including the type hash `(12 + 1) * 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)))
                }
            }
        }
        // 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 that notably
        /// does not revert when calling a non-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(getLastTansferResult(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(getLastTansferResult(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 getLastTansferResult(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")
                        }
                }
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-or-later
        pragma solidity ^0.7.6;
        import "../interfaces/IERC20.sol";
        import "../mixins/GPv2Signing.sol";
        import "./GPv2Order.sol";
        /// @title Gnosis Protocol v2 Trade Library.
        /// @author Gnosis Developers
        library GPv2Trade {
            using GPv2Order for GPv2Order.Data;
            using GPv2Order for bytes;
            /// @dev A struct representing a trade to be executed as part a batch
            /// settlement.
            struct Data {
                uint256 sellTokenIndex;
                uint256 buyTokenIndex;
                address receiver;
                uint256 sellAmount;
                uint256 buyAmount;
                uint32 validTo;
                bytes32 appData;
                uint256 feeAmount;
                uint256 flags;
                uint256 executedAmount;
                bytes signature;
            }
            /// @dev Extracts the order data and signing scheme for the specified trade.
            ///
            /// @param trade The trade.
            /// @param tokens The list of tokens included in the settlement. The token
            /// indices in the trade parameters map to tokens in this array.
            /// @param order The memory location to extract the order data to.
            function extractOrder(
                Data calldata trade,
                IERC20[] calldata tokens,
                GPv2Order.Data memory order
            ) internal pure returns (GPv2Signing.Scheme signingScheme) {
                order.sellToken = tokens[trade.sellTokenIndex];
                order.buyToken = tokens[trade.buyTokenIndex];
                order.receiver = trade.receiver;
                order.sellAmount = trade.sellAmount;
                order.buyAmount = trade.buyAmount;
                order.validTo = trade.validTo;
                order.appData = trade.appData;
                order.feeAmount = trade.feeAmount;
                (
                    order.kind,
                    order.partiallyFillable,
                    order.sellTokenBalance,
                    order.buyTokenBalance,
                    signingScheme
                ) = extractFlags(trade.flags);
            }
            /// @dev Decodes trade flags.
            ///
            /// Trade flags are used to tightly encode information on how to decode
            /// an order. Examples that directly affect the structure of an order are
            /// the kind of order (either a sell or a buy order) as well as whether the
            /// order is partially fillable or if it is a "fill-or-kill" order. It also
            /// encodes the signature scheme used to validate the order. As the most
            /// likely values are fill-or-kill sell orders by an externally owned
            /// account, the flags are chosen such that `0x00` represents this kind of
            /// order. The flags byte uses the following format:
            ///
            /// ```
            /// bit | 31 ...   | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
            /// ----+----------+---+---+-------+---+---+
            ///     | reserved | *   * | * | *   * | * | * |
            ///                  |   |   |   |   |   |   |
            ///                  |   |   |   |   |   |   +---- order kind bit, 0 for a sell order
            ///                  |   |   |   |   |   |         and 1 for a buy order
            ///                  |   |   |   |   |   |
            ///                  |   |   |   |   |   +-------- order fill bit, 0 for fill-or-kill
            ///                  |   |   |   |   |             and 1 for a partially fillable order
            ///                  |   |   |   |   |
            ///                  |   |   |   +---+------------ use internal sell token balance bit:
            ///                  |   |   |                     0x: ERC20 token balance
            ///                  |   |   |                     10: external Balancer Vault balance
            ///                  |   |   |                     11: internal Balancer Vault balance
            ///                  |   |   |
            ///                  |   |   +-------------------- use buy token balance bit
            ///                  |   |                         0: ERC20 token balance
            ///                  |   |                         1: internal Balancer Vault balance
            ///                  |   |
            ///                  +---+------------------------ signature scheme bits:
            ///                                                00: EIP-712
            ///                                                01: eth_sign
            ///                                                10: EIP-1271
            ///                                                11: pre_sign
            /// ```
            function extractFlags(uint256 flags)
                internal
                pure
                returns (
                    bytes32 kind,
                    bool partiallyFillable,
                    bytes32 sellTokenBalance,
                    bytes32 buyTokenBalance,
                    GPv2Signing.Scheme signingScheme
                )
            {
                if (flags & 0x01 == 0) {
                    kind = GPv2Order.KIND_SELL;
                } else {
                    kind = GPv2Order.KIND_BUY;
                }
                partiallyFillable = flags & 0x02 != 0;
                if (flags & 0x08 == 0) {
                    sellTokenBalance = GPv2Order.BALANCE_ERC20;
                } else if (flags & 0x04 == 0) {
                    sellTokenBalance = GPv2Order.BALANCE_EXTERNAL;
                } else {
                    sellTokenBalance = GPv2Order.BALANCE_INTERNAL;
                }
                if (flags & 0x10 == 0) {
                    buyTokenBalance = GPv2Order.BALANCE_ERC20;
                } else {
                    buyTokenBalance = GPv2Order.BALANCE_INTERNAL;
                }
                // NOTE: Take advantage of the fact that Solidity will revert if the
                // following expression does not produce a valid enum value. This means
                // we check here that the leading reserved bits must be 0.
                signingScheme = GPv2Signing.Scheme(flags >> 5);
            }
        }
        // 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)
                }
            }
        }
        // SPDX-License-Identifier: MIT
        // Vendored from OpenZeppelin contracts with minor modifications:
        // - Modified Solidity version
        // - Formatted code
        // - Shortened revert messages
        // - Removed unused methods
        // - Convert to `type(*).*` notation
        // <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/utils/SafeCast.sol>
        pragma solidity ^0.7.6;
        /**
         * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
         * checks.
         *
         * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
         * easily result in undesired exploitation or bugs, since developers usually
         * assume that overflows raise errors. `SafeCast` restores this intuition by
         * reverting the transaction when such an operation overflows.
         *
         * Using this library instead of the unchecked operations eliminates an entire
         * class of bugs, so it's recommended to use it always.
         *
         * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
         * all math on `uint256` and `int256` and then downcasting.
         */
        library SafeCast {
            /**
             * @dev Converts a signed int256 into an unsigned uint256.
             *
             * Requirements:
             *
             * - input must be greater than or equal to 0.
             */
            function toUint256(int256 value) internal pure returns (uint256) {
                require(value >= 0, "SafeCast: not positive");
                return uint256(value);
            }
            /**
             * @dev Converts an unsigned uint256 into a signed int256.
             *
             * Requirements:
             *
             * - input must be less than or equal to maxInt256.
             */
            function toInt256(uint256 value) internal pure returns (int256) {
                require(
                    value <= uint256(type(int256).max),
                    "SafeCast: int256 overflow"
                );
                return int256(value);
            }
        }
        // SPDX-License-Identifier: MIT
        // Vendored from OpenZeppelin contracts with minor modifications:
        // - Modified Solidity version
        // - Formatted code
        // - Shortened some revert messages
        // - Removed unused methods
        // - Added `ceilDiv` method
        // <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/math/SafeMath.sol>
        pragma solidity ^0.7.6;
        /**
         * @dev Wrappers over Solidity's arithmetic operations with added overflow
         * checks.
         *
         * Arithmetic operations in Solidity wrap on overflow. This can easily result
         * in bugs, because programmers usually assume that an overflow raises an
         * error, which is the standard behavior in high level programming languages.
         * `SafeMath` restores this intuition by reverting the transaction when an
         * operation overflows.
         *
         * Using this library instead of the unchecked operations eliminates an entire
         * class of bugs, so it's recommended to use it always.
         */
        library SafeMath {
            /**
             * @dev Returns the addition of two unsigned integers, reverting on
             * overflow.
             *
             * Counterpart to Solidity's `+` operator.
             *
             * Requirements:
             *
             * - Addition cannot overflow.
             */
            function add(uint256 a, uint256 b) internal pure returns (uint256) {
                uint256 c = a + b;
                require(c >= a, "SafeMath: addition overflow");
                return c;
            }
            /**
             * @dev Returns the subtraction of two unsigned integers, reverting on
             * overflow (when the result is negative).
             *
             * Counterpart to Solidity's `-` operator.
             *
             * Requirements:
             *
             * - Subtraction cannot overflow.
             */
            function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                require(b <= a, "SafeMath: subtraction overflow");
                return a - b;
            }
            /**
             * @dev Returns the multiplication of two unsigned integers, reverting on
             * overflow.
             *
             * Counterpart to Solidity's `*` operator.
             *
             * Requirements:
             *
             * - Multiplication cannot overflow.
             */
            function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                if (a == 0) return 0;
                uint256 c = a * b;
                require(c / a == b, "SafeMath: mul overflow");
                return c;
            }
            /**
             * @dev Returns the integer division of two unsigned integers, reverting on
             * division by zero. The result is rounded towards zero.
             *
             * Counterpart to Solidity's `/` operator. Note: this function uses a
             * `revert` opcode (which leaves remaining gas untouched) while Solidity
             * uses an invalid opcode to revert (consuming all remaining gas).
             *
             * Requirements:
             *
             * - The divisor cannot be zero.
             */
            function div(uint256 a, uint256 b) internal pure returns (uint256) {
                require(b > 0, "SafeMath: division by 0");
                return a / b;
            }
            /**
             * @dev Returns the ceiling integer division of two unsigned integers,
             * reverting on division by zero. The result is rounded towards up the
             * nearest integer, instead of truncating the fractional part.
             *
             * Requirements:
             *
             * - The divisor cannot be zero.
             * - The sum of the dividend and divisor cannot overflow.
             */
            function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
                require(b > 0, "SafeMath: ceiling division by 0");
                return a / b + (a % b == 0 ? 0 : 1);
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-or-later
        pragma solidity ^0.7.6;
        import "../interfaces/GPv2EIP1271.sol";
        import "../libraries/GPv2Order.sol";
        import "../libraries/GPv2Trade.sol";
        /// @title Gnosis Protocol v2 Signing Library.
        /// @author Gnosis Developers
        abstract contract GPv2Signing {
            using GPv2Order for GPv2Order.Data;
            using GPv2Order for bytes;
            /// @dev Recovered trade data containing the extracted order and the
            /// recovered owner address.
            struct RecoveredOrder {
                GPv2Order.Data data;
                bytes uid;
                address owner;
                address receiver;
            }
            /// @dev Signing scheme used for recovery.
            enum Scheme {Eip712, EthSign, Eip1271, PreSign}
            /// @dev The EIP-712 domain type hash used for computing the domain
            /// separator.
            bytes32 private constant DOMAIN_TYPE_HASH =
                keccak256(
                    "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
                );
            /// @dev The EIP-712 domain name used for computing the domain separator.
            bytes32 private constant DOMAIN_NAME = keccak256("Gnosis Protocol");
            /// @dev The EIP-712 domain version used for computing the domain separator.
            bytes32 private constant DOMAIN_VERSION = keccak256("v2");
            /// @dev Marker value indicating an order is pre-signed.
            uint256 private constant PRE_SIGNED =
                uint256(keccak256("GPv2Signing.Scheme.PreSign"));
            /// @dev The domain separator used for signing orders that gets mixed in
            /// making signatures for different domains incompatible. This domain
            /// separator is computed following the EIP-712 standard and has replay
            /// protection mixed in so that signed orders are only valid for specific
            /// GPv2 contracts.
            bytes32 public immutable domainSeparator;
            /// @dev Storage indicating whether or not an order has been signed by a
            /// particular address.
            mapping(bytes => uint256) public preSignature;
            /// @dev Event that is emitted when an account either pre-signs an order or
            /// revokes an existing pre-signature.
            event PreSignature(address indexed owner, bytes orderUid, bool signed);
            constructor() {
                // NOTE: Currently, the only way to get the chain ID in solidity is
                // using assembly.
                uint256 chainId;
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    chainId := chainid()
                }
                domainSeparator = keccak256(
                    abi.encode(
                        DOMAIN_TYPE_HASH,
                        DOMAIN_NAME,
                        DOMAIN_VERSION,
                        chainId,
                        address(this)
                    )
                );
            }
            /// @dev Sets a presignature for the specified order UID.
            ///
            /// @param orderUid The unique identifier of the order to pre-sign.
            function setPreSignature(bytes calldata orderUid, bool signed) external {
                (, address owner, ) = orderUid.extractOrderUidParams();
                require(owner == msg.sender, "GPv2: cannot presign order");
                if (signed) {
                    preSignature[orderUid] = PRE_SIGNED;
                } else {
                    preSignature[orderUid] = 0;
                }
                emit PreSignature(owner, orderUid, signed);
            }
            /// @dev Returns an empty recovered order with a pre-allocated buffer for
            /// packing the unique identifier.
            ///
            /// @return recoveredOrder The empty recovered order data.
            function allocateRecoveredOrder()
                internal
                pure
                returns (RecoveredOrder memory recoveredOrder)
            {
                recoveredOrder.uid = new bytes(GPv2Order.UID_LENGTH);
            }
            /// @dev Extracts order data and recovers the signer from the specified
            /// trade.
            ///
            /// @param recoveredOrder Memory location used for writing the recovered order data.
            /// @param tokens The list of tokens included in the settlement. The token
            /// indices in the trade parameters map to tokens in this array.
            /// @param trade The trade data to recover the order data from.
            function recoverOrderFromTrade(
                RecoveredOrder memory recoveredOrder,
                IERC20[] calldata tokens,
                GPv2Trade.Data calldata trade
            ) internal view {
                GPv2Order.Data memory order = recoveredOrder.data;
                Scheme signingScheme = GPv2Trade.extractOrder(trade, tokens, order);
                (bytes32 orderDigest, address owner) =
                    recoverOrderSigner(order, signingScheme, trade.signature);
                recoveredOrder.uid.packOrderUidParams(
                    orderDigest,
                    owner,
                    order.validTo
                );
                recoveredOrder.owner = owner;
                recoveredOrder.receiver = order.actualReceiver(owner);
            }
            /// @dev The length of any signature from an externally owned account.
            uint256 private constant ECDSA_SIGNATURE_LENGTH = 65;
            /// @dev Recovers an order's signer from the specified order and signature.
            ///
            /// @param order The order to recover a signature for.
            /// @param signingScheme The signing scheme.
            /// @param signature The signature bytes.
            /// @return orderDigest The computed order hash.
            /// @return owner The recovered address from the specified signature.
            function recoverOrderSigner(
                GPv2Order.Data memory order,
                Scheme signingScheme,
                bytes calldata signature
            ) internal view returns (bytes32 orderDigest, address owner) {
                orderDigest = order.hash(domainSeparator);
                if (signingScheme == Scheme.Eip712) {
                    owner = recoverEip712Signer(orderDigest, signature);
                } else if (signingScheme == Scheme.EthSign) {
                    owner = recoverEthsignSigner(orderDigest, signature);
                } else if (signingScheme == Scheme.Eip1271) {
                    owner = recoverEip1271Signer(orderDigest, signature);
                } else {
                    // signingScheme == Scheme.PreSign
                    owner = recoverPreSigner(orderDigest, signature, order.validTo);
                }
            }
            /// @dev Perform an ECDSA recover for the specified message and calldata
            /// signature.
            ///
            /// The signature is encoded by tighyly packing the following struct:
            /// ```
            /// struct EncodedSignature {
            ///     bytes32 r;
            ///     bytes32 s;
            ///     uint8 v;
            /// }
            /// ```
            ///
            /// @param message The signed message.
            /// @param encodedSignature The encoded signature.
            function ecdsaRecover(bytes32 message, bytes calldata encodedSignature)
                internal
                pure
                returns (address signer)
            {
                require(
                    encodedSignature.length == ECDSA_SIGNATURE_LENGTH,
                    "GPv2: malformed ecdsa signature"
                );
                bytes32 r;
                bytes32 s;
                uint8 v;
                // NOTE: Use assembly to efficiently decode signature data.
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    // r = uint256(encodedSignature[0:32])
                    r := calldataload(encodedSignature.offset)
                    // s = uint256(encodedSignature[32:64])
                    s := calldataload(add(encodedSignature.offset, 32))
                    // v = uint8(encodedSignature[64])
                    v := shr(248, calldataload(add(encodedSignature.offset, 64)))
                }
                signer = ecrecover(message, v, r, s);
                require(signer != address(0), "GPv2: invalid ecdsa signature");
            }
            /// @dev Decodes signature bytes originating from an EIP-712-encoded
            /// signature.
            ///
            /// EIP-712 signs typed data. The specifications are described in the
            /// related EIP (<https://eips.ethereum.org/EIPS/eip-712>).
            ///
            /// EIP-712 signatures are encoded as standard ECDSA signatures as described
            /// in the corresponding decoding function [`ecdsaRecover`].
            ///
            /// @param orderDigest The EIP-712 signing digest derived from the order
            /// parameters.
            /// @param encodedSignature Calldata pointing to tightly packed signature
            /// bytes.
            /// @return owner The address of the signer.
            function recoverEip712Signer(
                bytes32 orderDigest,
                bytes calldata encodedSignature
            ) internal pure returns (address owner) {
                owner = ecdsaRecover(orderDigest, encodedSignature);
            }
            /// @dev Decodes signature bytes originating from the output of the eth_sign
            /// RPC call.
            ///
            /// The specifications are described in the Ethereum documentation
            /// (<https://eth.wiki/json-rpc/API#eth_sign>).
            ///
            /// eth_sign signatures are encoded as standard ECDSA signatures as
            /// described in the corresponding decoding function
            /// [`ecdsaRecover`].
            ///
            /// @param orderDigest The EIP-712 signing digest derived from the order
            /// parameters.
            /// @param encodedSignature Calldata pointing to tightly packed signature
            /// bytes.
            /// @return owner The address of the signer.
            function recoverEthsignSigner(
                bytes32 orderDigest,
                bytes calldata encodedSignature
            ) internal pure returns (address owner) {
                // The signed message is encoded as:
                // `"\\x19Ethereum Signed Message:\
        " || length || data`, where
                // the length is a constant (32 bytes) and the data is defined as:
                // `orderDigest`.
                bytes32 ethsignDigest =
                    keccak256(
                        abi.encodePacked(
                            "\\x19Ethereum Signed Message:\
        32",
                            orderDigest
                        )
                    );
                owner = ecdsaRecover(ethsignDigest, encodedSignature);
            }
            /// @dev Verifies the input calldata as an EIP-1271 contract signature and
            /// returns the address of the signer.
            ///
            /// The encoded signature tightly packs the following struct:
            ///
            /// ```
            /// struct EncodedEip1271Signature {
            ///     address owner;
            ///     bytes signature;
            /// }
            /// ```
            ///
            /// This function enforces that the encoded data stores enough bytes to
            /// cover the full length of the decoded signature.
            ///
            /// @param encodedSignature The encoded EIP-1271 signature.
            /// @param orderDigest The EIP-712 signing digest derived from the order
            /// parameters.
            /// @return owner The address of the signer.
            function recoverEip1271Signer(
                bytes32 orderDigest,
                bytes calldata encodedSignature
            ) internal view returns (address owner) {
                // NOTE: Use assembly to read the verifier address from the encoded
                // signature bytes.
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    // owner = address(encodedSignature[0:20])
                    owner := shr(96, calldataload(encodedSignature.offset))
                }
                // NOTE: Configure prettier to ignore the following line as it causes
                // a panic in the Solidity plugin.
                // prettier-ignore
                bytes calldata signature = encodedSignature[20:];
                require(
                    EIP1271Verifier(owner).isValidSignature(orderDigest, signature) ==
                        GPv2EIP1271.MAGICVALUE,
                    "GPv2: invalid eip1271 signature"
                );
            }
            /// @dev Verifies the order has been pre-signed. The signature is the
            /// address of the signer of the order.
            ///
            /// @param orderDigest The EIP-712 signing digest derived from the order
            /// parameters.
            /// @param encodedSignature The pre-sign signature reprenting the order UID.
            /// @param validTo The order expiry timestamp.
            /// @return owner The address of the signer.
            function recoverPreSigner(
                bytes32 orderDigest,
                bytes calldata encodedSignature,
                uint32 validTo
            ) internal view returns (address owner) {
                require(encodedSignature.length == 20, "GPv2: malformed presignature");
                // NOTE: Use assembly to read the owner address from the encoded
                // signature bytes.
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    // owner = address(encodedSignature[0:20])
                    owner := shr(96, calldataload(encodedSignature.offset))
                }
                bytes memory orderUid = new bytes(GPv2Order.UID_LENGTH);
                orderUid.packOrderUidParams(orderDigest, owner, validTo);
                require(
                    preSignature[orderUid] == PRE_SIGNED,
                    "GPv2: order not presigned"
                );
            }
        }
        // SPDX-License-Identifier: MIT
        // Vendored from OpenZeppelin contracts with minor modifications:
        // - Modified Solidity version
        // - Formatted code
        // <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/utils/ReentrancyGuard.sol>
        pragma solidity ^0.7.6;
        /**
         * @dev Contract module that helps prevent reentrant calls to a function.
         *
         * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
         * available, which can be applied to functions to make sure there are no nested
         * (reentrant) calls to them.
         *
         * Note that because there is a single `nonReentrant` guard, functions marked as
         * `nonReentrant` may not call one another. This can be worked around by making
         * those functions `private`, and then adding `external` `nonReentrant` entry
         * points to them.
         *
         * TIP: If you would like to learn more about reentrancy and alternative ways
         * to protect against it, check out our blog post
         * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
         */
        abstract contract ReentrancyGuard {
            // Booleans are more expensive than uint256 or any type that takes up a full
            // word because each write operation emits an extra SLOAD to first read the
            // slot's contents, replace the bits taken up by the boolean, and then write
            // back. This is the compiler's defense against contract upgrades and
            // pointer aliasing, and it cannot be disabled.
            // The values being non-zero value makes deployment a bit more expensive,
            // but in exchange the refund on every call to nonReentrant will be lower in
            // amount. Since refunds are capped to a percentage of the total
            // transaction's gas, it is best to keep them low in cases like this one, to
            // increase the likelihood of the full refund coming into effect.
            uint256 private constant _NOT_ENTERED = 1;
            uint256 private constant _ENTERED = 2;
            uint256 private _status;
            constructor() {
                _status = _NOT_ENTERED;
            }
            /**
             * @dev Prevents a contract from calling itself, directly or indirectly.
             * Calling a `nonReentrant` function from another `nonReentrant`
             * function is not supported. It is possible to prevent this from happening
             * by making the `nonReentrant` function external, and make it call a
             * `private` function that does the actual work.
             */
            modifier nonReentrant() {
                // On the first call to nonReentrant, _notEntered will be true
                require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
                // Any calls to nonReentrant after this point will fail
                _status = _ENTERED;
                _;
                // By storing the original value once again, a refund is triggered (see
                // https://eips.ethereum.org/EIPS/eip-2200)
                _status = _NOT_ENTERED;
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        // Vendored from Gnosis utility contracts with minor modifications:
        // - Modified Solidity version
        // - Formatted code
        // - Added linter directives to ignore low level call and assembly warnings
        // <https://github.com/gnosis/util-contracts/blob/v3.1.0-solc-7/contracts/StorageAccessible.sol>
        pragma solidity ^0.7.6;
        /// @title ViewStorageAccessible - Interface on top of StorageAccessible base class to allow simulations from view functions
        interface ViewStorageAccessible {
            /**
             * @dev Same as `simulateDelegatecall` on StorageAccessible. Marked as view so that it can be called from external contracts
             * that want to run simulations from within view functions. Will revert if the invoked simulation attempts to change state.
             */
            function simulateDelegatecall(
                address targetContract,
                bytes memory calldataPayload
            ) external view returns (bytes memory);
            /**
             * @dev Same as `getStorageAt` on StorageAccessible. This method allows reading aribtrary ranges of storage.
             */
            function getStorageAt(uint256 offset, uint256 length)
                external
                view
                returns (bytes memory);
        }
        /// @title StorageAccessible - generic base contract that allows callers to access all internal storage.
        contract StorageAccessible {
            /**
             * @dev Reads `length` bytes of storage in the currents contract
             * @param offset - the offset in the current contract's storage in words to start reading from
             * @param length - the number of words (32 bytes) of data to read
             * @return the bytes that were read.
             */
            function getStorageAt(uint256 offset, uint256 length)
                external
                view
                returns (bytes memory)
            {
                bytes memory result = new bytes(length * 32);
                for (uint256 index = 0; index < length; index++) {
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        let word := sload(add(offset, index))
                        mstore(add(add(result, 0x20), mul(index, 0x20)), word)
                    }
                }
                return result;
            }
            /**
             * @dev Performs a delegetecall on a targetContract in the context of self.
             * Internally reverts execution to avoid side effects (making it static). Catches revert and returns encoded result as bytes.
             * @param targetContract Address of the contract containing the code to execute.
             * @param calldataPayload Calldata that should be sent to the target contract (encoded method name and arguments).
             */
            function simulateDelegatecall(
                address targetContract,
                bytes memory calldataPayload
            ) public returns (bytes memory response) {
                bytes memory innerCall =
                    abi.encodeWithSelector(
                        this.simulateDelegatecallInternal.selector,
                        targetContract,
                        calldataPayload
                    );
                // solhint-disable-next-line avoid-low-level-calls
                (, response) = address(this).call(innerCall);
                bool innerSuccess = response[response.length - 1] == 0x01;
                setLength(response, response.length - 1);
                if (innerSuccess) {
                    return response;
                } else {
                    revertWith(response);
                }
            }
            /**
             * @dev Performs a delegetecall on a targetContract in the context of self.
             * Internally reverts execution to avoid side effects (making it static). Returns encoded result as revert message
             * concatenated with the success flag of the inner call as a last byte.
             * @param targetContract Address of the contract containing the code to execute.
             * @param calldataPayload Calldata that should be sent to the target contract (encoded method name and arguments).
             */
            function simulateDelegatecallInternal(
                address targetContract,
                bytes memory calldataPayload
            ) external returns (bytes memory response) {
                bool success;
                // solhint-disable-next-line avoid-low-level-calls
                (success, response) = targetContract.delegatecall(calldataPayload);
                revertWith(abi.encodePacked(response, success));
            }
            function revertWith(bytes memory response) internal pure {
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    revert(add(response, 0x20), mload(response))
                }
            }
            function setLength(bytes memory buffer, uint256 length) internal pure {
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    mstore(buffer, length)
                }
            }
        }
        

        File 4 of 5: GnosisSafe
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        import "./base/ModuleManager.sol";
        import "./base/OwnerManager.sol";
        import "./base/FallbackManager.sol";
        import "./base/GuardManager.sol";
        import "./common/EtherPaymentFallback.sol";
        import "./common/Singleton.sol";
        import "./common/SignatureDecoder.sol";
        import "./common/SecuredTokenTransfer.sol";
        import "./common/StorageAccessible.sol";
        import "./interfaces/ISignatureValidator.sol";
        import "./external/GnosisSafeMath.sol";
        /// @title Gnosis Safe - A multisignature wallet with support for confirmations using signed messages based on ERC191.
        /// @author Stefan George - <[email protected]>
        /// @author Richard Meissner - <[email protected]>
        contract GnosisSafe is
            EtherPaymentFallback,
            Singleton,
            ModuleManager,
            OwnerManager,
            SignatureDecoder,
            SecuredTokenTransfer,
            ISignatureValidatorConstants,
            FallbackManager,
            StorageAccessible,
            GuardManager
        {
            using GnosisSafeMath for uint256;
            string public constant VERSION = "1.3.0";
            // keccak256(
            //     "EIP712Domain(uint256 chainId,address verifyingContract)"
            // );
            bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218;
            // keccak256(
            //     "SafeTx(address to,uint256 value,bytes data,uint8 operation,uint256 safeTxGas,uint256 baseGas,uint256 gasPrice,address gasToken,address refundReceiver,uint256 nonce)"
            // );
            bytes32 private constant SAFE_TX_TYPEHASH = 0xbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d8;
            event SafeSetup(address indexed initiator, address[] owners, uint256 threshold, address initializer, address fallbackHandler);
            event ApproveHash(bytes32 indexed approvedHash, address indexed owner);
            event SignMsg(bytes32 indexed msgHash);
            event ExecutionFailure(bytes32 txHash, uint256 payment);
            event ExecutionSuccess(bytes32 txHash, uint256 payment);
            uint256 public nonce;
            bytes32 private _deprecatedDomainSeparator;
            // Mapping to keep track of all message hashes that have been approve by ALL REQUIRED owners
            mapping(bytes32 => uint256) public signedMessages;
            // Mapping to keep track of all hashes (message or transaction) that have been approve by ANY owners
            mapping(address => mapping(bytes32 => uint256)) public approvedHashes;
            // This constructor ensures that this contract can only be used as a master copy for Proxy contracts
            constructor() {
                // By setting the threshold it is not possible to call setup anymore,
                // so we create a Safe with 0 owners and threshold 1.
                // This is an unusable Safe, perfect for the singleton
                threshold = 1;
            }
            /// @dev Setup function sets initial storage of contract.
            /// @param _owners List of Safe owners.
            /// @param _threshold Number of required confirmations for a Safe transaction.
            /// @param to Contract address for optional delegate call.
            /// @param data Data payload for optional delegate call.
            /// @param fallbackHandler Handler for fallback calls to this contract
            /// @param paymentToken Token that should be used for the payment (0 is ETH)
            /// @param payment Value that should be paid
            /// @param paymentReceiver Adddress that should receive the payment (or 0 if tx.origin)
            function setup(
                address[] calldata _owners,
                uint256 _threshold,
                address to,
                bytes calldata data,
                address fallbackHandler,
                address paymentToken,
                uint256 payment,
                address payable paymentReceiver
            ) external {
                // setupOwners checks if the Threshold is already set, therefore preventing that this method is called twice
                setupOwners(_owners, _threshold);
                if (fallbackHandler != address(0)) internalSetFallbackHandler(fallbackHandler);
                // As setupOwners can only be called if the contract has not been initialized we don't need a check for setupModules
                setupModules(to, data);
                if (payment > 0) {
                    // To avoid running into issues with EIP-170 we reuse the handlePayment function (to avoid adjusting code of that has been verified we do not adjust the method itself)
                    // baseGas = 0, gasPrice = 1 and gas = payment => amount = (payment + 0) * 1 = payment
                    handlePayment(payment, 0, 1, paymentToken, paymentReceiver);
                }
                emit SafeSetup(msg.sender, _owners, _threshold, to, fallbackHandler);
            }
            /// @dev Allows to execute a Safe transaction confirmed by required number of owners and then pays the account that submitted the transaction.
            ///      Note: The fees are always transferred, even if the user transaction fails.
            /// @param to Destination address of Safe transaction.
            /// @param value Ether value of Safe transaction.
            /// @param data Data payload of Safe transaction.
            /// @param operation Operation type of Safe transaction.
            /// @param safeTxGas Gas that should be used for the Safe transaction.
            /// @param baseGas Gas costs that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)
            /// @param gasPrice Gas price that should be used for the payment calculation.
            /// @param gasToken Token address (or 0 if ETH) that is used for the payment.
            /// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
            /// @param signatures Packed signature data ({bytes32 r}{bytes32 s}{uint8 v})
            function execTransaction(
                address to,
                uint256 value,
                bytes calldata data,
                Enum.Operation operation,
                uint256 safeTxGas,
                uint256 baseGas,
                uint256 gasPrice,
                address gasToken,
                address payable refundReceiver,
                bytes memory signatures
            ) public payable virtual returns (bool success) {
                bytes32 txHash;
                // Use scope here to limit variable lifetime and prevent `stack too deep` errors
                {
                    bytes memory txHashData =
                        encodeTransactionData(
                            // Transaction info
                            to,
                            value,
                            data,
                            operation,
                            safeTxGas,
                            // Payment info
                            baseGas,
                            gasPrice,
                            gasToken,
                            refundReceiver,
                            // Signature info
                            nonce
                        );
                    // Increase nonce and execute transaction.
                    nonce++;
                    txHash = keccak256(txHashData);
                    checkSignatures(txHash, txHashData, signatures);
                }
                address guard = getGuard();
                {
                    if (guard != address(0)) {
                        Guard(guard).checkTransaction(
                            // Transaction info
                            to,
                            value,
                            data,
                            operation,
                            safeTxGas,
                            // Payment info
                            baseGas,
                            gasPrice,
                            gasToken,
                            refundReceiver,
                            // Signature info
                            signatures,
                            msg.sender
                        );
                    }
                }
                // We require some gas to emit the events (at least 2500) after the execution and some to perform code until the execution (500)
                // We also include the 1/64 in the check that is not send along with a call to counteract potential shortings because of EIP-150
                require(gasleft() >= ((safeTxGas * 64) / 63).max(safeTxGas + 2500) + 500, "GS010");
                // Use scope here to limit variable lifetime and prevent `stack too deep` errors
                {
                    uint256 gasUsed = gasleft();
                    // If the gasPrice is 0 we assume that nearly all available gas can be used (it is always more than safeTxGas)
                    // We only substract 2500 (compared to the 3000 before) to ensure that the amount passed is still higher than safeTxGas
                    success = execute(to, value, data, operation, gasPrice == 0 ? (gasleft() - 2500) : safeTxGas);
                    gasUsed = gasUsed.sub(gasleft());
                    // If no safeTxGas and no gasPrice was set (e.g. both are 0), then the internal tx is required to be successful
                    // This makes it possible to use `estimateGas` without issues, as it searches for the minimum gas where the tx doesn't revert
                    require(success || safeTxGas != 0 || gasPrice != 0, "GS013");
                    // We transfer the calculated tx costs to the tx.origin to avoid sending it to intermediate contracts that have made calls
                    uint256 payment = 0;
                    if (gasPrice > 0) {
                        payment = handlePayment(gasUsed, baseGas, gasPrice, gasToken, refundReceiver);
                    }
                    if (success) emit ExecutionSuccess(txHash, payment);
                    else emit ExecutionFailure(txHash, payment);
                }
                {
                    if (guard != address(0)) {
                        Guard(guard).checkAfterExecution(txHash, success);
                    }
                }
            }
            function handlePayment(
                uint256 gasUsed,
                uint256 baseGas,
                uint256 gasPrice,
                address gasToken,
                address payable refundReceiver
            ) private returns (uint256 payment) {
                // solhint-disable-next-line avoid-tx-origin
                address payable receiver = refundReceiver == address(0) ? payable(tx.origin) : refundReceiver;
                if (gasToken == address(0)) {
                    // For ETH we will only adjust the gas price to not be higher than the actual used gas price
                    payment = gasUsed.add(baseGas).mul(gasPrice < tx.gasprice ? gasPrice : tx.gasprice);
                    require(receiver.send(payment), "GS011");
                } else {
                    payment = gasUsed.add(baseGas).mul(gasPrice);
                    require(transferToken(gasToken, receiver, payment), "GS012");
                }
            }
            /**
             * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise.
             * @param dataHash Hash of the data (could be either a message hash or transaction hash)
             * @param data That should be signed (this is passed to an external validator contract)
             * @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash.
             */
            function checkSignatures(
                bytes32 dataHash,
                bytes memory data,
                bytes memory signatures
            ) public view {
                // Load threshold to avoid multiple storage loads
                uint256 _threshold = threshold;
                // Check that a threshold is set
                require(_threshold > 0, "GS001");
                checkNSignatures(dataHash, data, signatures, _threshold);
            }
            /**
             * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise.
             * @param dataHash Hash of the data (could be either a message hash or transaction hash)
             * @param data That should be signed (this is passed to an external validator contract)
             * @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash.
             * @param requiredSignatures Amount of required valid signatures.
             */
            function checkNSignatures(
                bytes32 dataHash,
                bytes memory data,
                bytes memory signatures,
                uint256 requiredSignatures
            ) public view {
                // Check that the provided signature data is not too short
                require(signatures.length >= requiredSignatures.mul(65), "GS020");
                // There cannot be an owner with address 0.
                address lastOwner = address(0);
                address currentOwner;
                uint8 v;
                bytes32 r;
                bytes32 s;
                uint256 i;
                for (i = 0; i < requiredSignatures; i++) {
                    (v, r, s) = signatureSplit(signatures, i);
                    if (v == 0) {
                        // If v is 0 then it is a contract signature
                        // When handling contract signatures the address of the contract is encoded into r
                        currentOwner = address(uint160(uint256(r)));
                        // Check that signature data pointer (s) is not pointing inside the static part of the signatures bytes
                        // This check is not completely accurate, since it is possible that more signatures than the threshold are send.
                        // Here we only check that the pointer is not pointing inside the part that is being processed
                        require(uint256(s) >= requiredSignatures.mul(65), "GS021");
                        // Check that signature data pointer (s) is in bounds (points to the length of data -> 32 bytes)
                        require(uint256(s).add(32) <= signatures.length, "GS022");
                        // Check if the contract signature is in bounds: start of data is s + 32 and end is start + signature length
                        uint256 contractSignatureLen;
                        // solhint-disable-next-line no-inline-assembly
                        assembly {
                            contractSignatureLen := mload(add(add(signatures, s), 0x20))
                        }
                        require(uint256(s).add(32).add(contractSignatureLen) <= signatures.length, "GS023");
                        // Check signature
                        bytes memory contractSignature;
                        // solhint-disable-next-line no-inline-assembly
                        assembly {
                            // The signature data for contract signatures is appended to the concatenated signatures and the offset is stored in s
                            contractSignature := add(add(signatures, s), 0x20)
                        }
                        require(ISignatureValidator(currentOwner).isValidSignature(data, contractSignature) == EIP1271_MAGIC_VALUE, "GS024");
                    } else if (v == 1) {
                        // If v is 1 then it is an approved hash
                        // When handling approved hashes the address of the approver is encoded into r
                        currentOwner = address(uint160(uint256(r)));
                        // Hashes are automatically approved by the sender of the message or when they have been pre-approved via a separate transaction
                        require(msg.sender == currentOwner || approvedHashes[currentOwner][dataHash] != 0, "GS025");
                    } else if (v > 30) {
                        // If v > 30 then default va (27,28) has been adjusted for eth_sign flow
                        // To support eth_sign and similar we adjust v and hash the messageHash with the Ethereum message prefix before applying ecrecover
                        currentOwner = ecrecover(keccak256(abi.encodePacked("\\x19Ethereum Signed Message:\
        32", dataHash)), v - 4, r, s);
                    } else {
                        // Default is the ecrecover flow with the provided data hash
                        // Use ecrecover with the messageHash for EOA signatures
                        currentOwner = ecrecover(dataHash, v, r, s);
                    }
                    require(currentOwner > lastOwner && owners[currentOwner] != address(0) && currentOwner != SENTINEL_OWNERS, "GS026");
                    lastOwner = currentOwner;
                }
            }
            /// @dev Allows to estimate a Safe transaction.
            ///      This method is only meant for estimation purpose, therefore the call will always revert and encode the result in the revert data.
            ///      Since the `estimateGas` function includes refunds, call this method to get an estimated of the costs that are deducted from the safe with `execTransaction`
            /// @param to Destination address of Safe transaction.
            /// @param value Ether value of Safe transaction.
            /// @param data Data payload of Safe transaction.
            /// @param operation Operation type of Safe transaction.
            /// @return Estimate without refunds and overhead fees (base transaction and payload data gas costs).
            /// @notice Deprecated in favor of common/StorageAccessible.sol and will be removed in next version.
            function requiredTxGas(
                address to,
                uint256 value,
                bytes calldata data,
                Enum.Operation operation
            ) external returns (uint256) {
                uint256 startGas = gasleft();
                // We don't provide an error message here, as we use it to return the estimate
                require(execute(to, value, data, operation, gasleft()));
                uint256 requiredGas = startGas - gasleft();
                // Convert response to string and return via error message
                revert(string(abi.encodePacked(requiredGas)));
            }
            /**
             * @dev Marks a hash as approved. This can be used to validate a hash that is used by a signature.
             * @param hashToApprove The hash that should be marked as approved for signatures that are verified by this contract.
             */
            function approveHash(bytes32 hashToApprove) external {
                require(owners[msg.sender] != address(0), "GS030");
                approvedHashes[msg.sender][hashToApprove] = 1;
                emit ApproveHash(hashToApprove, msg.sender);
            }
            /// @dev Returns the chain id used by this contract.
            function getChainId() public view returns (uint256) {
                uint256 id;
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    id := chainid()
                }
                return id;
            }
            function domainSeparator() public view returns (bytes32) {
                return keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, getChainId(), this));
            }
            /// @dev Returns the bytes that are hashed to be signed by owners.
            /// @param to Destination address.
            /// @param value Ether value.
            /// @param data Data payload.
            /// @param operation Operation type.
            /// @param safeTxGas Gas that should be used for the safe transaction.
            /// @param baseGas Gas costs for that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)
            /// @param gasPrice Maximum gas price that should be used for this transaction.
            /// @param gasToken Token address (or 0 if ETH) that is used for the payment.
            /// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
            /// @param _nonce Transaction nonce.
            /// @return Transaction hash bytes.
            function encodeTransactionData(
                address to,
                uint256 value,
                bytes calldata data,
                Enum.Operation operation,
                uint256 safeTxGas,
                uint256 baseGas,
                uint256 gasPrice,
                address gasToken,
                address refundReceiver,
                uint256 _nonce
            ) public view returns (bytes memory) {
                bytes32 safeTxHash =
                    keccak256(
                        abi.encode(
                            SAFE_TX_TYPEHASH,
                            to,
                            value,
                            keccak256(data),
                            operation,
                            safeTxGas,
                            baseGas,
                            gasPrice,
                            gasToken,
                            refundReceiver,
                            _nonce
                        )
                    );
                return abi.encodePacked(bytes1(0x19), bytes1(0x01), domainSeparator(), safeTxHash);
            }
            /// @dev Returns hash to be signed by owners.
            /// @param to Destination address.
            /// @param value Ether value.
            /// @param data Data payload.
            /// @param operation Operation type.
            /// @param safeTxGas Fas that should be used for the safe transaction.
            /// @param baseGas Gas costs for data used to trigger the safe transaction.
            /// @param gasPrice Maximum gas price that should be used for this transaction.
            /// @param gasToken Token address (or 0 if ETH) that is used for the payment.
            /// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
            /// @param _nonce Transaction nonce.
            /// @return Transaction hash.
            function getTransactionHash(
                address to,
                uint256 value,
                bytes calldata data,
                Enum.Operation operation,
                uint256 safeTxGas,
                uint256 baseGas,
                uint256 gasPrice,
                address gasToken,
                address refundReceiver,
                uint256 _nonce
            ) public view returns (bytes32) {
                return keccak256(encodeTransactionData(to, value, data, operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, _nonce));
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        import "../common/Enum.sol";
        /// @title Executor - A contract that can execute transactions
        /// @author Richard Meissner - <[email protected]>
        contract Executor {
            function execute(
                address to,
                uint256 value,
                bytes memory data,
                Enum.Operation operation,
                uint256 txGas
            ) internal returns (bool success) {
                if (operation == Enum.Operation.DelegateCall) {
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)
                    }
                } else {
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)
                    }
                }
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        import "../common/SelfAuthorized.sol";
        /// @title Fallback Manager - A contract that manages fallback calls made to this contract
        /// @author Richard Meissner - <[email protected]>
        contract FallbackManager is SelfAuthorized {
            event ChangedFallbackHandler(address handler);
            // keccak256("fallback_manager.handler.address")
            bytes32 internal constant FALLBACK_HANDLER_STORAGE_SLOT = 0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d5;
            function internalSetFallbackHandler(address handler) internal {
                bytes32 slot = FALLBACK_HANDLER_STORAGE_SLOT;
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    sstore(slot, handler)
                }
            }
            /// @dev Allows to add a contract to handle fallback calls.
            ///      Only fallback calls without value and with data will be forwarded.
            ///      This can only be done via a Safe transaction.
            /// @param handler contract to handle fallbacks calls.
            function setFallbackHandler(address handler) public authorized {
                internalSetFallbackHandler(handler);
                emit ChangedFallbackHandler(handler);
            }
            // solhint-disable-next-line payable-fallback,no-complex-fallback
            fallback() external {
                bytes32 slot = FALLBACK_HANDLER_STORAGE_SLOT;
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let handler := sload(slot)
                    if iszero(handler) {
                        return(0, 0)
                    }
                    calldatacopy(0, 0, calldatasize())
                    // The msg.sender address is shifted to the left by 12 bytes to remove the padding
                    // Then the address without padding is stored right after the calldata
                    mstore(calldatasize(), shl(96, caller()))
                    // Add 20 bytes for the address appended add the end
                    let success := call(gas(), handler, 0, 0, add(calldatasize(), 20), 0, 0)
                    returndatacopy(0, 0, returndatasize())
                    if iszero(success) {
                        revert(0, returndatasize())
                    }
                    return(0, returndatasize())
                }
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        import "../common/Enum.sol";
        import "../common/SelfAuthorized.sol";
        interface Guard {
            function checkTransaction(
                address to,
                uint256 value,
                bytes memory data,
                Enum.Operation operation,
                uint256 safeTxGas,
                uint256 baseGas,
                uint256 gasPrice,
                address gasToken,
                address payable refundReceiver,
                bytes memory signatures,
                address msgSender
            ) external;
            function checkAfterExecution(bytes32 txHash, bool success) external;
        }
        /// @title Fallback Manager - A contract that manages fallback calls made to this contract
        /// @author Richard Meissner - <[email protected]>
        contract GuardManager is SelfAuthorized {
            event ChangedGuard(address guard);
            // keccak256("guard_manager.guard.address")
            bytes32 internal constant GUARD_STORAGE_SLOT = 0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8;
            /// @dev Set a guard that checks transactions before execution
            /// @param guard The address of the guard to be used or the 0 address to disable the guard
            function setGuard(address guard) external authorized {
                bytes32 slot = GUARD_STORAGE_SLOT;
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    sstore(slot, guard)
                }
                emit ChangedGuard(guard);
            }
            function getGuard() internal view returns (address guard) {
                bytes32 slot = GUARD_STORAGE_SLOT;
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    guard := sload(slot)
                }
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        import "../common/Enum.sol";
        import "../common/SelfAuthorized.sol";
        import "./Executor.sol";
        /// @title Module Manager - A contract that manages modules that can execute transactions via this contract
        /// @author Stefan George - <[email protected]>
        /// @author Richard Meissner - <[email protected]>
        contract ModuleManager is SelfAuthorized, Executor {
            event EnabledModule(address module);
            event DisabledModule(address module);
            event ExecutionFromModuleSuccess(address indexed module);
            event ExecutionFromModuleFailure(address indexed module);
            address internal constant SENTINEL_MODULES = address(0x1);
            mapping(address => address) internal modules;
            function setupModules(address to, bytes memory data) internal {
                require(modules[SENTINEL_MODULES] == address(0), "GS100");
                modules[SENTINEL_MODULES] = SENTINEL_MODULES;
                if (to != address(0))
                    // Setup has to complete successfully or transaction fails.
                    require(execute(to, 0, data, Enum.Operation.DelegateCall, gasleft()), "GS000");
            }
            /// @dev Allows to add a module to the whitelist.
            ///      This can only be done via a Safe transaction.
            /// @notice Enables the module `module` for the Safe.
            /// @param module Module to be whitelisted.
            function enableModule(address module) public authorized {
                // Module address cannot be null or sentinel.
                require(module != address(0) && module != SENTINEL_MODULES, "GS101");
                // Module cannot be added twice.
                require(modules[module] == address(0), "GS102");
                modules[module] = modules[SENTINEL_MODULES];
                modules[SENTINEL_MODULES] = module;
                emit EnabledModule(module);
            }
            /// @dev Allows to remove a module from the whitelist.
            ///      This can only be done via a Safe transaction.
            /// @notice Disables the module `module` for the Safe.
            /// @param prevModule Module that pointed to the module to be removed in the linked list
            /// @param module Module to be removed.
            function disableModule(address prevModule, address module) public authorized {
                // Validate module address and check that it corresponds to module index.
                require(module != address(0) && module != SENTINEL_MODULES, "GS101");
                require(modules[prevModule] == module, "GS103");
                modules[prevModule] = modules[module];
                modules[module] = address(0);
                emit DisabledModule(module);
            }
            /// @dev Allows a Module to execute a Safe transaction without any further confirmations.
            /// @param to Destination address of module transaction.
            /// @param value Ether value of module transaction.
            /// @param data Data payload of module transaction.
            /// @param operation Operation type of module transaction.
            function execTransactionFromModule(
                address to,
                uint256 value,
                bytes memory data,
                Enum.Operation operation
            ) public virtual returns (bool success) {
                // Only whitelisted modules are allowed.
                require(msg.sender != SENTINEL_MODULES && modules[msg.sender] != address(0), "GS104");
                // Execute transaction without further confirmations.
                success = execute(to, value, data, operation, gasleft());
                if (success) emit ExecutionFromModuleSuccess(msg.sender);
                else emit ExecutionFromModuleFailure(msg.sender);
            }
            /// @dev Allows a Module to execute a Safe transaction without any further confirmations and return data
            /// @param to Destination address of module transaction.
            /// @param value Ether value of module transaction.
            /// @param data Data payload of module transaction.
            /// @param operation Operation type of module transaction.
            function execTransactionFromModuleReturnData(
                address to,
                uint256 value,
                bytes memory data,
                Enum.Operation operation
            ) public returns (bool success, bytes memory returnData) {
                success = execTransactionFromModule(to, value, data, operation);
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    // Load free memory location
                    let ptr := mload(0x40)
                    // We allocate memory for the return data by setting the free memory location to
                    // current free memory location + data size + 32 bytes for data size value
                    mstore(0x40, add(ptr, add(returndatasize(), 0x20)))
                    // Store the size
                    mstore(ptr, returndatasize())
                    // Store the data
                    returndatacopy(add(ptr, 0x20), 0, returndatasize())
                    // Point the return data to the correct memory location
                    returnData := ptr
                }
            }
            /// @dev Returns if an module is enabled
            /// @return True if the module is enabled
            function isModuleEnabled(address module) public view returns (bool) {
                return SENTINEL_MODULES != module && modules[module] != address(0);
            }
            /// @dev Returns array of modules.
            /// @param start Start of the page.
            /// @param pageSize Maximum number of modules that should be returned.
            /// @return array Array of modules.
            /// @return next Start of the next page.
            function getModulesPaginated(address start, uint256 pageSize) external view returns (address[] memory array, address next) {
                // Init array with max page size
                array = new address[](pageSize);
                // Populate return array
                uint256 moduleCount = 0;
                address currentModule = modules[start];
                while (currentModule != address(0x0) && currentModule != SENTINEL_MODULES && moduleCount < pageSize) {
                    array[moduleCount] = currentModule;
                    currentModule = modules[currentModule];
                    moduleCount++;
                }
                next = currentModule;
                // Set correct size of returned array
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    mstore(array, moduleCount)
                }
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        import "../common/SelfAuthorized.sol";
        /// @title OwnerManager - Manages a set of owners and a threshold to perform actions.
        /// @author Stefan George - <[email protected]>
        /// @author Richard Meissner - <[email protected]>
        contract OwnerManager is SelfAuthorized {
            event AddedOwner(address owner);
            event RemovedOwner(address owner);
            event ChangedThreshold(uint256 threshold);
            address internal constant SENTINEL_OWNERS = address(0x1);
            mapping(address => address) internal owners;
            uint256 internal ownerCount;
            uint256 internal threshold;
            /// @dev Setup function sets initial storage of contract.
            /// @param _owners List of Safe owners.
            /// @param _threshold Number of required confirmations for a Safe transaction.
            function setupOwners(address[] memory _owners, uint256 _threshold) internal {
                // Threshold can only be 0 at initialization.
                // Check ensures that setup function can only be called once.
                require(threshold == 0, "GS200");
                // Validate that threshold is smaller than number of added owners.
                require(_threshold <= _owners.length, "GS201");
                // There has to be at least one Safe owner.
                require(_threshold >= 1, "GS202");
                // Initializing Safe owners.
                address currentOwner = SENTINEL_OWNERS;
                for (uint256 i = 0; i < _owners.length; i++) {
                    // Owner address cannot be null.
                    address owner = _owners[i];
                    require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this) && currentOwner != owner, "GS203");
                    // No duplicate owners allowed.
                    require(owners[owner] == address(0), "GS204");
                    owners[currentOwner] = owner;
                    currentOwner = owner;
                }
                owners[currentOwner] = SENTINEL_OWNERS;
                ownerCount = _owners.length;
                threshold = _threshold;
            }
            /// @dev Allows to add a new owner to the Safe and update the threshold at the same time.
            ///      This can only be done via a Safe transaction.
            /// @notice Adds the owner `owner` to the Safe and updates the threshold to `_threshold`.
            /// @param owner New owner address.
            /// @param _threshold New threshold.
            function addOwnerWithThreshold(address owner, uint256 _threshold) public authorized {
                // Owner address cannot be null, the sentinel or the Safe itself.
                require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this), "GS203");
                // No duplicate owners allowed.
                require(owners[owner] == address(0), "GS204");
                owners[owner] = owners[SENTINEL_OWNERS];
                owners[SENTINEL_OWNERS] = owner;
                ownerCount++;
                emit AddedOwner(owner);
                // Change threshold if threshold was changed.
                if (threshold != _threshold) changeThreshold(_threshold);
            }
            /// @dev Allows to remove an owner from the Safe and update the threshold at the same time.
            ///      This can only be done via a Safe transaction.
            /// @notice Removes the owner `owner` from the Safe and updates the threshold to `_threshold`.
            /// @param prevOwner Owner that pointed to the owner to be removed in the linked list
            /// @param owner Owner address to be removed.
            /// @param _threshold New threshold.
            function removeOwner(
                address prevOwner,
                address owner,
                uint256 _threshold
            ) public authorized {
                // Only allow to remove an owner, if threshold can still be reached.
                require(ownerCount - 1 >= _threshold, "GS201");
                // Validate owner address and check that it corresponds to owner index.
                require(owner != address(0) && owner != SENTINEL_OWNERS, "GS203");
                require(owners[prevOwner] == owner, "GS205");
                owners[prevOwner] = owners[owner];
                owners[owner] = address(0);
                ownerCount--;
                emit RemovedOwner(owner);
                // Change threshold if threshold was changed.
                if (threshold != _threshold) changeThreshold(_threshold);
            }
            /// @dev Allows to swap/replace an owner from the Safe with another address.
            ///      This can only be done via a Safe transaction.
            /// @notice Replaces the owner `oldOwner` in the Safe with `newOwner`.
            /// @param prevOwner Owner that pointed to the owner to be replaced in the linked list
            /// @param oldOwner Owner address to be replaced.
            /// @param newOwner New owner address.
            function swapOwner(
                address prevOwner,
                address oldOwner,
                address newOwner
            ) public authorized {
                // Owner address cannot be null, the sentinel or the Safe itself.
                require(newOwner != address(0) && newOwner != SENTINEL_OWNERS && newOwner != address(this), "GS203");
                // No duplicate owners allowed.
                require(owners[newOwner] == address(0), "GS204");
                // Validate oldOwner address and check that it corresponds to owner index.
                require(oldOwner != address(0) && oldOwner != SENTINEL_OWNERS, "GS203");
                require(owners[prevOwner] == oldOwner, "GS205");
                owners[newOwner] = owners[oldOwner];
                owners[prevOwner] = newOwner;
                owners[oldOwner] = address(0);
                emit RemovedOwner(oldOwner);
                emit AddedOwner(newOwner);
            }
            /// @dev Allows to update the number of required confirmations by Safe owners.
            ///      This can only be done via a Safe transaction.
            /// @notice Changes the threshold of the Safe to `_threshold`.
            /// @param _threshold New threshold.
            function changeThreshold(uint256 _threshold) public authorized {
                // Validate that threshold is smaller than number of owners.
                require(_threshold <= ownerCount, "GS201");
                // There has to be at least one Safe owner.
                require(_threshold >= 1, "GS202");
                threshold = _threshold;
                emit ChangedThreshold(threshold);
            }
            function getThreshold() public view returns (uint256) {
                return threshold;
            }
            function isOwner(address owner) public view returns (bool) {
                return owner != SENTINEL_OWNERS && owners[owner] != address(0);
            }
            /// @dev Returns array of owners.
            /// @return Array of Safe owners.
            function getOwners() public view returns (address[] memory) {
                address[] memory array = new address[](ownerCount);
                // populate return array
                uint256 index = 0;
                address currentOwner = owners[SENTINEL_OWNERS];
                while (currentOwner != SENTINEL_OWNERS) {
                    array[index] = currentOwner;
                    currentOwner = owners[currentOwner];
                    index++;
                }
                return array;
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        /// @title Enum - Collection of enums
        /// @author Richard Meissner - <[email protected]>
        contract Enum {
            enum Operation {Call, DelegateCall}
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        /// @title EtherPaymentFallback - A contract that has a fallback to accept ether payments
        /// @author Richard Meissner - <[email protected]>
        contract EtherPaymentFallback {
            event SafeReceived(address indexed sender, uint256 value);
            /// @dev Fallback function accepts Ether transactions.
            receive() external payable {
                emit SafeReceived(msg.sender, msg.value);
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        /// @title SecuredTokenTransfer - Secure token transfer
        /// @author Richard Meissner - <[email protected]>
        contract SecuredTokenTransfer {
            /// @dev Transfers a token and returns if it was a success
            /// @param token Token that should be transferred
            /// @param receiver Receiver to whom the token should be transferred
            /// @param amount The amount of tokens that should be transferred
            function transferToken(
                address token,
                address receiver,
                uint256 amount
            ) internal returns (bool transferred) {
                // 0xa9059cbb - keccack("transfer(address,uint256)")
                bytes memory data = abi.encodeWithSelector(0xa9059cbb, receiver, amount);
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    // We write the return value to scratch space.
                    // See https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html#layout-in-memory
                    let success := call(sub(gas(), 10000), token, 0, add(data, 0x20), mload(data), 0, 0x20)
                    switch returndatasize()
                        case 0 {
                            transferred := success
                        }
                        case 0x20 {
                            transferred := iszero(or(iszero(success), iszero(mload(0))))
                        }
                        default {
                            transferred := 0
                        }
                }
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        /// @title SelfAuthorized - authorizes current contract to perform actions
        /// @author Richard Meissner - <[email protected]>
        contract SelfAuthorized {
            function requireSelfCall() private view {
                require(msg.sender == address(this), "GS031");
            }
            modifier authorized() {
                // This is a function call as it minimized the bytecode size
                requireSelfCall();
                _;
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        /// @title SignatureDecoder - Decodes signatures that a encoded as bytes
        /// @author Richard Meissner - <[email protected]>
        contract SignatureDecoder {
            /// @dev divides bytes signature into `uint8 v, bytes32 r, bytes32 s`.
            /// @notice Make sure to peform a bounds check for @param pos, to avoid out of bounds access on @param signatures
            /// @param pos which signature to read. A prior bounds check of this parameter should be performed, to avoid out of bounds access
            /// @param signatures concatenated rsv signatures
            function signatureSplit(bytes memory signatures, uint256 pos)
                internal
                pure
                returns (
                    uint8 v,
                    bytes32 r,
                    bytes32 s
                )
            {
                // The signature format is a compact form of:
                //   {bytes32 r}{bytes32 s}{uint8 v}
                // Compact means, uint8 is not padded to 32 bytes.
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let signaturePos := mul(0x41, pos)
                    r := mload(add(signatures, add(signaturePos, 0x20)))
                    s := mload(add(signatures, add(signaturePos, 0x40)))
                    // Here we are loading the last 32 bytes, including 31 bytes
                    // of 's'. There is no 'mload8' to do this.
                    //
                    // 'byte' is not working due to the Solidity parser, so lets
                    // use the second best option, 'and'
                    v := and(mload(add(signatures, add(signaturePos, 0x41))), 0xff)
                }
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        /// @title Singleton - Base for singleton contracts (should always be first super contract)
        ///         This contract is tightly coupled to our proxy contract (see `proxies/GnosisSafeProxy.sol`)
        /// @author Richard Meissner - <[email protected]>
        contract Singleton {
            // singleton always needs to be first declared variable, to ensure that it is at the same location as in the Proxy contract.
            // It should also always be ensured that the address is stored alone (uses a full word)
            address private singleton;
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        /// @title StorageAccessible - generic base contract that allows callers to access all internal storage.
        /// @notice See https://github.com/gnosis/util-contracts/blob/bb5fe5fb5df6d8400998094fb1b32a178a47c3a1/contracts/StorageAccessible.sol
        contract StorageAccessible {
            /**
             * @dev Reads `length` bytes of storage in the currents contract
             * @param offset - the offset in the current contract's storage in words to start reading from
             * @param length - the number of words (32 bytes) of data to read
             * @return the bytes that were read.
             */
            function getStorageAt(uint256 offset, uint256 length) public view returns (bytes memory) {
                bytes memory result = new bytes(length * 32);
                for (uint256 index = 0; index < length; index++) {
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        let word := sload(add(offset, index))
                        mstore(add(add(result, 0x20), mul(index, 0x20)), word)
                    }
                }
                return result;
            }
            /**
             * @dev Performs a delegetecall on a targetContract in the context of self.
             * Internally reverts execution to avoid side effects (making it static).
             *
             * This method reverts with data equal to `abi.encode(bool(success), bytes(response))`.
             * Specifically, the `returndata` after a call to this method will be:
             * `success:bool || response.length:uint256 || response:bytes`.
             *
             * @param targetContract Address of the contract containing the code to execute.
             * @param calldataPayload Calldata that should be sent to the target contract (encoded method name and arguments).
             */
            function simulateAndRevert(address targetContract, bytes memory calldataPayload) external {
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let success := delegatecall(gas(), targetContract, add(calldataPayload, 0x20), mload(calldataPayload), 0, 0)
                    mstore(0x00, success)
                    mstore(0x20, returndatasize())
                    returndatacopy(0x40, 0, returndatasize())
                    revert(0, add(returndatasize(), 0x40))
                }
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        /**
         * @title GnosisSafeMath
         * @dev Math operations with safety checks that revert on error
         * Renamed from SafeMath to GnosisSafeMath to avoid conflicts
         * TODO: remove once open zeppelin update to solc 0.5.0
         */
        library GnosisSafeMath {
            /**
             * @dev Multiplies two numbers, reverts on overflow.
             */
            function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                // benefit is lost if 'b' is also tested.
                // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                if (a == 0) {
                    return 0;
                }
                uint256 c = a * b;
                require(c / a == b);
                return c;
            }
            /**
             * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
             */
            function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                require(b <= a);
                uint256 c = a - b;
                return c;
            }
            /**
             * @dev Adds two numbers, reverts on overflow.
             */
            function add(uint256 a, uint256 b) internal pure returns (uint256) {
                uint256 c = a + b;
                require(c >= a);
                return c;
            }
            /**
             * @dev Returns the largest of two numbers.
             */
            function max(uint256 a, uint256 b) internal pure returns (uint256) {
                return a >= b ? a : b;
            }
        }
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        contract ISignatureValidatorConstants {
            // bytes4(keccak256("isValidSignature(bytes,bytes)")
            bytes4 internal constant EIP1271_MAGIC_VALUE = 0x20c13b0b;
        }
        abstract contract ISignatureValidator is ISignatureValidatorConstants {
            /**
             * @dev Should return whether the signature provided is valid for the provided data
             * @param _data Arbitrary length data signed on the behalf of address(this)
             * @param _signature Signature byte array associated with _data
             *
             * MUST return the bytes4 magic value 0x20c13b0b when function passes.
             * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)
             * MUST allow external calls
             */
            function isValidSignature(bytes memory _data, bytes memory _signature) public view virtual returns (bytes4);
        }
        

        File 5 of 5: MultiSendCallOnly
        // SPDX-License-Identifier: LGPL-3.0-only
        pragma solidity >=0.7.0 <0.9.0;
        /// @title Multi Send Call Only - Allows to batch multiple transactions into one, but only calls
        /// @author Stefan George - <[email protected]>
        /// @author Richard Meissner - <[email protected]>
        /// @notice The guard logic is not required here as this contract doesn't support nested delegate calls
        contract MultiSendCallOnly {
            /// @dev Sends multiple transactions and reverts all if one fails.
            /// @param transactions Encoded transactions. Each transaction is encoded as a packed bytes of
            ///                     operation has to be uint8(0) in this version (=> 1 byte),
            ///                     to as a address (=> 20 bytes),
            ///                     value as a uint256 (=> 32 bytes),
            ///                     data length as a uint256 (=> 32 bytes),
            ///                     data as bytes.
            ///                     see abi.encodePacked for more information on packed encoding
            /// @notice The code is for most part the same as the normal MultiSend (to keep compatibility),
            ///         but reverts if a transaction tries to use a delegatecall.
            /// @notice This method is payable as delegatecalls keep the msg.value from the previous call
            ///         If the calling method (e.g. execTransaction) received ETH this would revert otherwise
            function multiSend(bytes memory transactions) public payable {
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let length := mload(transactions)
                    let i := 0x20
                    for {
                        // Pre block is not used in "while mode"
                    } lt(i, length) {
                        // Post block is not used in "while mode"
                    } {
                        // First byte of the data is the operation.
                        // We shift by 248 bits (256 - 8 [operation byte]) it right since mload will always load 32 bytes (a word).
                        // This will also zero out unused data.
                        let operation := shr(0xf8, mload(add(transactions, i)))
                        // We offset the load address by 1 byte (operation byte)
                        // We shift it right by 96 bits (256 - 160 [20 address bytes]) to right-align the data and zero out unused data.
                        let to := shr(0x60, mload(add(transactions, add(i, 0x01))))
                        // We offset the load address by 21 byte (operation byte + 20 address bytes)
                        let value := mload(add(transactions, add(i, 0x15)))
                        // We offset the load address by 53 byte (operation byte + 20 address bytes + 32 value bytes)
                        let dataLength := mload(add(transactions, add(i, 0x35)))
                        // We offset the load address by 85 byte (operation byte + 20 address bytes + 32 value bytes + 32 data length bytes)
                        let data := add(transactions, add(i, 0x55))
                        let success := 0
                        switch operation
                            case 0 {
                                success := call(gas(), to, value, data, dataLength, 0, 0)
                            }
                            // This version does not allow delegatecalls
                            case 1 {
                                revert(0, 0)
                            }
                        if eq(success, 0) {
                            revert(0, 0)
                        }
                        // Next entry starts at 85 byte + data length
                        i := add(i, add(0x55, dataLength))
                    }
                }
            }
        }