POL Price: $0.704112 (-0.61%)
Gas: 32 GWei
 

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Stake ETH497993012023-11-11 4:01:48393 days ago1699675308IN
Solid World: Zap Staking
35 POL0.17445253200.96783342
Stake ETH497992712023-11-11 4:00:44393 days ago1699675244IN
Solid World: Zap Staking
35 POL0.27144805208.49169562
Stake Single Swa...497703642023-11-10 10:49:32394 days ago1699613372IN
Solid World: Zap Staking
0 POL0.19098343244
Stake Single Swa...497230492023-11-09 6:25:42395 days ago1699511142IN
Solid World: Zap Staking
0 POL0.17326821207.88203096
Stake Single Swa...490285022023-10-22 18:34:31412 days ago1697999671IN
Solid World: Zap Staking
0 POL0.12021476133.01668736
Stake Single Swa...487959702023-10-16 18:59:51418 days ago1697482791IN
Solid World: Zap Staking
0 POL0.13533466156.78632851
Stake ETH487036822023-10-14 9:57:22421 days ago1697277442IN
Solid World: Zap Staking
150 POL0.0481045843.51627591
Stake ETH487035582023-10-14 9:52:58421 days ago1697277178IN
Solid World: Zap Staking
500 POL0.0724004965.50658271
Stake ETH487034692023-10-14 9:49:48421 days ago1697276988IN
Solid World: Zap Staking
250 POL0.0753228167.28904109
Stake Single Swa...486207662023-10-12 7:27:24423 days ago1697095644IN
Solid World: Zap Staking
0 POL0.0676032174
Stake Single Swa...485540452023-10-10 14:19:21425 days ago1696947561IN
Solid World: Zap Staking
0 POL0.0766336888.82953955
Stake Single Swa...483137442023-10-04 10:45:14431 days ago1696416314IN
Solid World: Zap Staking
0 POL0.0623365878.39482761
Stake Single Swa...483122962023-10-04 9:52:47431 days ago1696413167IN
Solid World: Zap Staking
0 POL0.10368637129.88884809
Stake Single Swa...483121122023-10-04 9:45:45431 days ago1696412745IN
Solid World: Zap Staking
0 POL0.0739733984.42533571
Stake Single Swa...483119202023-10-04 9:38:57431 days ago1696412337IN
Solid World: Zap Staking
0 POL0.0811456892.82608824
Stake Single Swa...483090182023-10-04 7:52:35431 days ago1696405955IN
Solid World: Zap Staking
0 POL0.0626365875.61472014
Stake Single Swa...482824392023-10-03 15:50:58431 days ago1696348258IN
Solid World: Zap Staking
0 POL0.08755723112
Stake Double Swa...482823552023-10-03 15:48:00431 days ago1696348080IN
Solid World: Zap Staking
0 POL0.13335812125
Stake ETH481450832023-09-30 2:22:37435 days ago1696040557IN
Solid World: Zap Staking
200 POL0.0973005366.41588892
Stake Single Swa...481215212023-09-29 11:48:25436 days ago1695988105IN
Solid World: Zap Staking
0 POL0.0616855477
Stake Single Swa...480870682023-09-28 14:25:00437 days ago1695911100IN
Solid World: Zap Staking
0 POL0.0784697790.57138083
Stake ETH480470232023-09-27 13:44:19438 days ago1695822259IN
Solid World: Zap Staking
5 POL0.0911774872
Stake ETH479751302023-09-25 17:21:08439 days ago1695662468IN
Solid World: Zap Staking
65 POL0.14438794129.5826133
Stake ETH478883042023-09-23 12:21:33442 days ago1695471693IN
Solid World: Zap Staking
2 POL0.0863461782.39806987
Stake ETH478882582023-09-23 12:19:55442 days ago1695471595IN
Solid World: Zap Staking
2 POL0.0852125182.15590267
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
497993012023-11-11 4:01:48393 days ago1699675308
Solid World: Zap Staking
35 POL
497992712023-11-11 4:00:44393 days ago1699675244
Solid World: Zap Staking
35 POL
487036822023-10-14 9:57:22421 days ago1697277442
Solid World: Zap Staking
150 POL
487035582023-10-14 9:52:58421 days ago1697277178
Solid World: Zap Staking
500 POL
487034692023-10-14 9:49:48421 days ago1697276988
Solid World: Zap Staking
250 POL
481450832023-09-30 2:22:37435 days ago1696040557
Solid World: Zap Staking
200 POL
480470232023-09-27 13:44:19438 days ago1695822259
Solid World: Zap Staking
5 POL
479751302023-09-25 17:21:08439 days ago1695662468
Solid World: Zap Staking
65 POL
478883042023-09-23 12:21:33442 days ago1695471693
Solid World: Zap Staking
2 POL
478882582023-09-23 12:19:55442 days ago1695471595
Solid World: Zap Staking
2 POL
478481782023-09-22 11:53:00443 days ago1695383580
Solid World: Zap Staking
110 POL
478221172023-09-21 20:06:37443 days ago1695326797
Solid World: Zap Staking
115 POL
477881862023-09-20 23:33:10444 days ago1695252790
Solid World: Zap Staking
2 POL
477876782023-09-20 23:15:05444 days ago1695251705
Solid World: Zap Staking
2 POL
476426852023-09-17 7:12:47448 days ago1694934767
Solid World: Zap Staking
98 POL
472997522023-09-08 15:58:45456 days ago1694188725
Solid World: Zap Staking
5.82317382 POL
471300912023-09-04 9:53:35461 days ago1693821215
Solid World: Zap Staking
2 POL
470900022023-09-03 9:36:26462 days ago1693733786
Solid World: Zap Staking
751 POL
470896332023-09-03 9:22:50462 days ago1693732970
Solid World: Zap Staking
751 POL
470891972023-09-03 9:07:17462 days ago1693732037
Solid World: Zap Staking
751.54176913 POL
469013802023-08-29 15:41:32466 days ago1693323692
Solid World: Zap Staking
175 POL
468959612023-08-29 12:22:21467 days ago1693311741
Solid World: Zap Staking
150 POL
467034092023-08-24 16:42:49471 days ago1692895369
Solid World: Zap Staking
10 POL
466991412023-08-24 14:07:33472 days ago1692886053
Solid World: Zap Staking
4 POL
466987142023-08-24 13:51:45472 days ago1692885105
Solid World: Zap Staking
16 POL
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SolidZapStaker

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion, BSL 1.1 license
File 1 of 14 : SolidZapStaker.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.18;

import "./BaseSolidZapStaker.sol";

/// @author Solid World
contract SolidZapStaker is BaseSolidZapStaker {
    using GPv2SafeERC20 for IERC20;

    constructor(
        address _router,
        address _weth,
        address _solidStaking
    ) BaseSolidZapStaker(_router, _weth, _solidStaking) {}

    /// @inheritdoc ISolidZapStaker
    function stakeDoubleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2,
        uint minShares,
        address zapRecipient
    ) external nonReentrant returns (uint) {
        _prepareToSwap(inputToken, inputAmount, router);
        return _stakeDoubleSwap(inputToken, inputAmount, hypervisor, swap1, swap2, minShares, zapRecipient);
    }

    /// @inheritdoc ISolidZapStaker
    function stakeDoubleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2,
        uint minShares
    ) external nonReentrant returns (uint) {
        _prepareToSwap(inputToken, inputAmount, router);
        return _stakeDoubleSwap(inputToken, inputAmount, hypervisor, swap1, swap2, minShares, msg.sender);
    }

    /// @inheritdoc ISolidZapStaker
    function stakeSingleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap,
        uint minShares,
        address zapRecipient
    ) external nonReentrant returns (uint) {
        return _stakeSingleSwap(inputToken, inputAmount, hypervisor, swap, minShares, zapRecipient);
    }

    /// @inheritdoc ISolidZapStaker
    function stakeSingleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap,
        uint minShares
    ) external nonReentrant returns (uint) {
        return _stakeSingleSwap(inputToken, inputAmount, hypervisor, swap, minShares, msg.sender);
    }

    /// @inheritdoc ISolidZapStaker
    function stakeETH(
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2,
        uint minShares,
        address zapRecipient
    ) external payable nonReentrant returns (uint) {
        _wrap(weth, msg.value);

        return _stakeDoubleSwap(weth, msg.value, hypervisor, swap1, swap2, minShares, zapRecipient);
    }

    /// @inheritdoc ISolidZapStaker
    function stakeETH(
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2,
        uint minShares
    ) external payable nonReentrant returns (uint) {
        _wrap(weth, msg.value);

        return _stakeDoubleSwap(weth, msg.value, hypervisor, swap1, swap2, minShares, msg.sender);
    }

    /// @inheritdoc ISolidZapStaker
    function simulateStakeDoubleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2
    )
        external
        nonReentrant
        returns (
            bool,
            uint,
            Fraction memory
        )
    {
        _prepareToSwap(inputToken, inputAmount, router);

        return _simulateStakeDoubleSwap(hypervisor, swap1, swap2);
    }

    /// @inheritdoc ISolidZapStaker
    function simulateStakeETH(
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2
    )
        external
        payable
        nonReentrant
        returns (
            bool,
            uint,
            Fraction memory
        )
    {
        _wrap(weth, msg.value);

        return _simulateStakeDoubleSwap(hypervisor, swap1, swap2);
    }

    /// @inheritdoc ISolidZapStaker
    function simulateStakeSingleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap
    )
        external
        nonReentrant
        returns (
            bool isDustless,
            uint shares,
            Fraction memory ratio
        )
    {
        SwapResults memory swapResults = _singleSwap(inputToken, inputAmount, hypervisor, swap);

        return _simulateLiquidityDeployment(hypervisor, swapResults);
    }

    function _simulateStakeDoubleSwap(
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2
    )
        private
        returns (
            bool,
            uint,
            Fraction memory
        )
    {
        SwapResults memory swapResults = _doubleSwap(hypervisor, swap1, swap2);
        return _simulateLiquidityDeployment(hypervisor, swapResults);
    }

    function _simulateLiquidityDeployment(address hypervisor, SwapResults memory swapResults)
        private
        returns (
            bool isDustless,
            uint shares,
            Fraction memory ratio
        )
    {
        (isDustless, ratio) = _checkDustless(hypervisor, swapResults);

        if (isDustless) {
            shares = _deployLiquidity(swapResults, hypervisor);
        }
    }

    function _stakeDoubleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2,
        uint minShares,
        address zapRecipient
    ) private returns (uint) {
        SwapResults memory swapResults = _doubleSwap(hypervisor, swap1, swap2);

        return _stake(inputToken, inputAmount, hypervisor, minShares, zapRecipient, swapResults);
    }

    function _stakeSingleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap,
        uint minShares,
        address zapRecipient
    ) private returns (uint) {
        SwapResults memory swapResults = _singleSwap(inputToken, inputAmount, hypervisor, swap);

        return _stake(inputToken, inputAmount, hypervisor, minShares, zapRecipient, swapResults);
    }

    function _stake(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        uint minShares,
        address zapRecipient,
        SwapResults memory swapResults
    ) private returns (uint shares) {
        shares = _deployLiquidity(swapResults, hypervisor);

        if (shares < minShares) {
            revert AcquiredSharesLessThanMin(shares, minShares);
        }

        _approveTokenSpendingIfNeeded(hypervisor, solidStaking);
        _stakeWithRecipient(hypervisor, shares, zapRecipient);

        emit ZapStake(zapRecipient, inputToken, inputAmount, shares);
    }

    function _doubleSwap(
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2
    ) private returns (SwapResults memory swapResults) {
        (address token0Address, address token1Address) = _fetchHypervisorTokens(hypervisor);
        (uint token0BalanceBefore, uint token1BalanceBefore) = _fetchTokenBalances(
            token0Address,
            token1Address
        );

        _swapViaRouter(router, swap1);
        _swapViaRouter(router, swap2);

        (uint token0BalanceAfter, uint token1BalanceAfter) = _fetchTokenBalances(
            token0Address,
            token1Address
        );

        if (token0BalanceAfter <= token0BalanceBefore || token1BalanceAfter <= token1BalanceBefore) {
            revert InvalidSwap();
        }

        swapResults.token0._address = token0Address;
        swapResults.token0.balance = token0BalanceAfter - token0BalanceBefore;

        swapResults.token1._address = token1Address;
        swapResults.token1.balance = token1BalanceAfter - token1BalanceBefore;
    }

    function _singleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap
    ) private returns (SwapResults memory swapResults) {
        (address token0Address, address token1Address) = _fetchHypervisorTokens(hypervisor);

        if (inputToken != token0Address && inputToken != token1Address) {
            revert InvalidInput();
        }

        (uint token0BalanceBefore, uint token1BalanceBefore) = _fetchTokenBalances(
            token0Address,
            token1Address
        );

        _prepareToSwap(inputToken, inputAmount, router);
        _swapViaRouter(router, swap);

        (uint token0BalanceAfter, uint token1BalanceAfter) = _fetchTokenBalances(
            token0Address,
            token1Address
        );

        if (token0BalanceAfter <= token0BalanceBefore || token1BalanceAfter <= token1BalanceBefore) {
            revert InvalidSwap();
        }

        swapResults.token0._address = token0Address;
        swapResults.token0.balance = token0BalanceAfter - token0BalanceBefore;

        swapResults.token1._address = token1Address;
        swapResults.token1.balance = token1BalanceAfter - token1BalanceBefore;
    }

    function _checkDustless(address hypervisor, SwapResults memory swapResults)
        private
        view
        returns (bool isDustless, Fraction memory actualRatio)
    {
        (uint amountStart, uint amountEnd) = IUniProxy(getUniProxy(hypervisor)).getDepositAmount(
            hypervisor,
            swapResults.token0._address,
            swapResults.token0.balance
        );

        isDustless = _between(swapResults.token1.balance, amountStart, amountEnd);

        if (!isDustless) {
            actualRatio = Fraction(swapResults.token0.balance, Math.average(amountStart, amountEnd));
        }
    }
}

File 2 of 14 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @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 making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

File 3 of 14 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

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

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

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

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

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

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

File 4 of 14 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}

File 5 of 14 : IHypervisor.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

/// @author Gamma Strategies
interface IHypervisor {
    function token0() external view returns (address);

    function token1() external view returns (address);

    function whitelistedAddress() external view returns (address);

    function pool() external view returns (address);
}

File 6 of 14 : IUniProxy.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

/// @author Gamma Strategies
interface IUniProxy {
    /// @notice Deposit into the given position
    /// @param deposit0 Amount of token0 to deposit
    /// @param deposit1 Amount of token1 to deposit
    /// @param to Address to receive liquidity tokens
    /// @param pos Hypervisor Address
    /// @param minIn Minimum amount of tokens that should be paid
    /// @return shares Amount of liquidity tokens received
    function deposit(
        uint deposit0,
        uint deposit1,
        address to,
        address pos,
        uint[4] memory minIn
    ) external returns (uint shares);

    /// @notice Get the amount of token to deposit for the given amount of pair token
    /// @param pos Hypervisor Address
    /// @param token Address of token to deposit
    /// @param depositAmount Amount of token to deposit
    /// @return amountStart Minimum amounts of the pair token to deposit
    /// @return amountEnd Maximum amounts of the pair token to deposit
    function getDepositAmount(
        address pos,
        address token,
        uint depositAmount
    ) external view returns (uint amountStart, uint amountEnd);
}

File 7 of 14 : ISolidStakingActions_0_8_18.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.18;

/// @title Permissionless state-mutating actions
/// @notice Contains state-mutating functions that can be called by anyone
/// @author Solid World DAO
interface ISolidStakingActions {
    /// @dev Stakes tokens for the caller into the staking contract
    /// @param token the token to stake
    /// @param amount the amount to stake
    function stake(address token, uint amount) external;

    /// @notice msg.sender stakes tokens for the recipient into the staking contract
    /// @dev funds are subtracted from msg.sender, stake is credited to recipient
    /// @param token the token to stake
    /// @param amount the amount to stake
    /// @param recipient the recipient of the stake
    function stake(
        address token,
        uint amount,
        address recipient
    ) external;

    /// @dev Withdraws tokens for the caller from the staking contract
    /// @param token the token to withdraw
    /// @param amount the amount to withdraw
    function withdraw(address token, uint amount) external;

    /// @dev Withdraws tokens for the caller from the staking contract
    /// @dev Claims all rewards of the incentivized `token` for the caller
    /// @param token the token to withdraw
    /// @param amount the amount to withdraw
    function withdrawStakeAndClaimRewards(address token, uint amount) external;
}

File 8 of 14 : IWETH.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

interface IWETH {
    function deposit() external payable;

    function withdraw(uint amount) external;

    function approve(address spender, uint amount) external returns (bool);
}

File 9 of 14 : ISWManager.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.18;

/// @author Solid World
/// @dev The minimal interface used to interact with SolidWorldManager
interface ISWManager {
    function collateralizeBatch(
        uint batchId,
        uint amountIn,
        uint amountOutMin
    ) external;

    function bulkDecollateralizeTokens(
        uint[] calldata batchIds,
        uint[] calldata amountsIn,
        uint[] calldata amountsOutMin
    ) external;

    function getBatchCategory(uint batchId) external view returns (uint);
}

File 10 of 14 : ISolidZapStaker.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.18;

/// @author Solid World
interface ISolidZapStaker {
    error AcquiredSharesLessThanMin(uint acquired, uint min);
    error InvalidSwap();

    event ZapStake(
        address indexed zapRecipient,
        address indexed inputToken,
        uint indexed inputAmount,
        uint shares
    );

    struct Fraction {
        uint numerator;
        uint denominator;
    }

    struct SwapResult {
        address _address;
        uint balance;
    }

    struct SwapResults {
        SwapResult token0;
        SwapResult token1;
    }

    function router() external view returns (address);

    function weth() external view returns (address);

    function solidStaking() external view returns (address);

    /// @notice Zap function that achieves the following:
    /// 1. Partially swaps `inputToken` to desired token via encoded swap1
    /// 2. Partially swaps `inputToken` to desired token via encoded swap2
    /// 3. Resulting tokens are deployed as liquidity via IUniProxy & `hypervisor`
    /// 4. Shares of the deployed liquidity are staked in `solidStaking`. `zapRecipient` is the beneficiary of the staked shares
    /// @notice The msg.sender must own `inputAmount` and approve this contract to spend `inputToken`
    /// @param inputToken The token used to provide liquidity
    /// @param inputAmount The amount of `inputToken` to use
    /// @param hypervisor The hypervisor used to deploy liquidity
    /// @param swap1 Encoded swap to partially swap `inputToken` to desired token
    /// @param swap2 Encoded swap to partially swap `inputToken` to desired token
    /// @param minShares The minimum amount of liquidity shares required for transaction to succeed
    /// @param zapRecipient The beneficiary of the staked shares
    /// @return shares The amount of shares staked in `solidStaking`
    function stakeDoubleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2,
        uint minShares,
        address zapRecipient
    ) external returns (uint shares);

    /// @notice Zap function that achieves the following:
    /// 1. Partially swaps `inputToken` to desired token via encoded swap1
    /// 2. Partially swaps `inputToken` to desired token via encoded swap2
    /// 3. Resulting tokens are deployed as liquidity via IUniProxy & `hypervisor`
    /// 4. Shares of the deployed liquidity are staked in `solidStaking`. `msg.sender` is the beneficiary of the staked shares
    /// @notice The msg.sender must own `inputAmount` and approve this contract to spend `inputToken`
    /// @param inputToken The token used to provide liquidity
    /// @param inputAmount The amount of `inputToken` to use
    /// @param hypervisor The hypervisor used to deploy liquidity
    /// @param swap1 Encoded swap to partially swap `inputToken` to desired token
    /// @param swap2 Encoded swap to partially swap `inputToken` to desired token
    /// @param minShares The minimum amount of liquidity shares required for transaction to succeed
    /// @return shares The amount of shares staked in `solidStaking`
    function stakeDoubleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2,
        uint minShares
    ) external returns (uint shares);

    /// @notice Zap function that achieves the following:
    /// 1. Partially (close to 50%) swaps `inputToken` to desired token via encoded swap
    /// 3. Resulting tokens are deployed as liquidity via IUniProxy & `hypervisor`
    /// 4. Shares of the deployed liquidity are staked in `solidStaking`. `zapRecipient` is the beneficiary of the staked shares
    /// @notice The msg.sender must own `inputAmount` and approve this contract to spend `inputToken`
    /// @notice `inputToken` must be one of hypervisor's token0 or token1
    /// @param inputToken The token used to provide liquidity
    /// @param inputAmount The amount of `inputToken` to use
    /// @param hypervisor The hypervisor used to deploy liquidity
    /// @param swap Encoded swap to partially swap `inputToken` to desired token
    /// @param minShares The minimum amount of liquidity shares required for transaction to succeed
    /// @param zapRecipient The beneficiary of the staked shares
    /// @return shares The amount of shares staked in `solidStaking`
    function stakeSingleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap,
        uint minShares,
        address zapRecipient
    ) external returns (uint shares);

    /// @notice Zap function that achieves the following:
    /// 1. Partially (close to 50%) swaps `inputToken` to desired token via encoded swap
    /// 3. Resulting tokens are deployed as liquidity via IUniProxy & `hypervisor`
    /// 4. Shares of the deployed liquidity are staked in `solidStaking`. `msg.sender` is the beneficiary of the staked shares
    /// @notice The msg.sender must own `inputAmount` and approve this contract to spend `inputToken`
    /// @notice `inputToken` must be one of hypervisor's token0 or token1
    /// @param inputToken The token used to provide liquidity
    /// @param inputAmount The amount of `inputToken` to use
    /// @param hypervisor The hypervisor used to deploy liquidity
    /// @param swap Encoded swap to partially swap `inputToken` to desired token
    /// @param minShares The minimum amount of liquidity shares required for transaction to succeed
    /// @return shares The amount of shares staked in `solidStaking`
    function stakeSingleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap,
        uint minShares
    ) external returns (uint shares);

    /// @notice Zap function that achieves the following:
    /// 1. Wraps `msg.value` to WETH
    /// 2. Partially swaps `WETH` to desired token via encoded swap1
    /// 3. Partially swaps `WETH` to desired token via encoded swap2
    /// 4. Resulting tokens are deployed as liquidity via IUniProxy & `hypervisor`
    /// 5. Shares of the deployed liquidity are staked in `solidStaking`. `zapRecipient` is the beneficiary of the staked shares
    /// @param hypervisor The hypervisor used to deploy liquidity
    /// @param swap1 Encoded swap to partially swap `WETH` to desired token
    /// @param swap2 Encoded swap to partially swap `WETH` to desired token
    /// @param minShares The minimum amount of liquidity shares required for transaction to succeed
    /// @param zapRecipient The beneficiary of the staked shares
    /// @return shares The amount of shares staked in `solidStaking`
    function stakeETH(
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2,
        uint minShares,
        address zapRecipient
    ) external payable returns (uint shares);

    /// @notice Zap function that achieves the following:
    /// 1. Wraps `msg.value` to WETH
    /// 2. Partially swaps `WETH` to desired token via encoded swap1
    /// 3. Partially swaps `WETH` to desired token via encoded swap2
    /// 4. Resulting tokens are deployed as liquidity via IUniProxy & `hypervisor`
    /// 5. Shares of the deployed liquidity are staked in `solidStaking`. `msg.sender` is the beneficiary of the staked shares
    /// @param hypervisor The hypervisor used to deploy liquidity
    /// @param swap1 Encoded swap to partially swap `WETH` to desired token
    /// @param swap2 Encoded swap to partially swap `WETH` to desired token
    /// @param minShares The minimum amount of liquidity shares required for transaction to succeed
    /// @return shares The amount of shares staked in `solidStaking`
    function stakeETH(
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2,
        uint minShares
    ) external payable returns (uint shares);

    /// @notice Function is meant to be called off-chain with _staticCall_.
    /// @notice Zap function that achieves the following:
    /// 1. Partially swaps `inputToken` to desired token via encoded swap1
    /// 2. Partially swaps `inputToken` to desired token via encoded swap2
    /// 3. Resulting tokens are checked against Gamma Vault to determine if they qualify for a dustless liquidity deployment
    ///     * if dustless, the function deploys the liquidity to obtain the amounts of shares getting minted and returns
    ///     * if not dustless, the function computes the current gamma token ratio and returns
    /// @notice The msg.sender must own `inputAmount` and approve this contract to spend `inputToken`
    /// @param inputToken The token used to provide liquidity
    /// @param inputAmount The amount of `inputToken` to use
    /// @param hypervisor The hypervisor used to deploy liquidity
    /// @param swap1 Encoded swap to partially swap `inputToken` to desired token
    /// @param swap2 Encoded swap to partially swap `inputToken` to desired token
    /// @return isDustless Whether the resulting tokens qualify for a dustless liquidity deployment
    /// @return shares The amount of shares minted from the dustless liquidity deployment
    /// @return ratio The current gamma token ratio, or empty if dustless
    function simulateStakeDoubleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2
    )
        external
        returns (
            bool isDustless,
            uint shares,
            Fraction memory ratio
        );

    /// @notice Function is meant to be called off-chain with _staticCall_.
    /// @notice Zap function that achieves the following:
    /// 1. Wraps `msg.value` to WETH
    /// 2. Partially swaps `WETH` to desired token via encoded swap1
    /// 3. Partially swaps `WETH` to desired token via encoded swap2
    /// 4. Resulting tokens are checked against Gamma Vault to determine if they qualify for a dustless liquidity deployment
    ///     * if dustless, the function deploys the liquidity to obtain the amounts of shares getting minted and returns
    ///     * if not dustless, the function computes the current gamma token ratio and returns
    /// @param hypervisor The hypervisor used to deploy liquidity
    /// @param swap1 Encoded swap to partially swap `WETH` to desired token
    /// @param swap2 Encoded swap to partially swap `WETH` to desired token
    /// @return isDustless Whether the resulting tokens qualify for a dustless liquidity deployment
    /// @return shares The amount of shares minted from the dustless liquidity deployment
    /// @return ratio The current gamma token ratio, or empty if dustless
    function simulateStakeETH(
        address hypervisor,
        bytes calldata swap1,
        bytes calldata swap2
    )
        external
        payable
        returns (
            bool isDustless,
            uint shares,
            Fraction memory ratio
        );

    /// @notice Function is meant to be called off-chain with _staticCall_.
    /// @notice Zap function that achieves the following:
    /// 1. Partially (close to 50%) swaps `inputToken` to desired token via encoded swap
    /// 2. Resulting tokens are checked against Gamma Vault to determine if they qualify for a dustless liquidity deployment
    ///     * if dustless, the function deploys the liquidity to obtain the amounts of shares getting minted and returns
    ///     * if not dustless, the function computes the current gamma token ratio and returns
    /// @notice The msg.sender must own `inputAmount` and approve this contract to spend `inputToken`
    /// @notice `inputToken` must be one of hypervisor's token0 or token1
    /// @param inputToken The token used to provide liquidity
    /// @param inputAmount The amount of `inputToken` to use
    /// @param hypervisor The hypervisor used to deploy liquidity
    /// @param swap Encoded swap to partially (close to 50%) swap `inputToken` to desired token
    /// @return isDustless Whether the resulting tokens qualify for a dustless liquidity deployment
    /// @return shares The amount of shares minted from the dustless liquidity deployment
    /// @return ratio The current gamma token ratio, or empty if dustless
    function simulateStakeSingleSwap(
        address inputToken,
        uint inputAmount,
        address hypervisor,
        bytes calldata swap
    )
        external
        returns (
            bool isDustless,
            uint shares,
            Fraction memory ratio
        );
}

File 11 of 14 : GPv2SafeERC20_0_8_18.sol
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity 0.8.18;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

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

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

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

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

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

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

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

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

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

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

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

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

File 12 of 14 : SafeTransferLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Simply use address for `token` parameter
library SafeTransferLib {
    function safeApprove(
        address token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "APPROVE_FAILED");
    }
}

File 13 of 14 : BaseZap.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.18;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../interfaces/staking/IWETH.sol";
import "../interfaces/zap/ISolidZapStaker.sol";
import "../interfaces/zap/ISWManager.sol";
import "../libraries/GPv2SafeERC20_0_8_18.sol";
import "../libraries/SafeTransferLib.sol";

/// @author Solid World
abstract contract BaseZap {
    using GPv2SafeERC20 for IERC20;
    using SafeTransferLib for address;

    error GenericSwapError();
    error InvalidInput();
    error SweepAmountZero();

    function _swapViaRouter(address router, bytes calldata encodedSwap) internal {
        (bool success, bytes memory retData) = router.call(encodedSwap);

        if (!success) {
            _propagateError(retData);
        }
    }

    function _propagateError(bytes memory revertReason) internal pure {
        if (revertReason.length == 0) {
            revert GenericSwapError();
        }

        assembly {
            revert(add(32, revertReason), mload(revertReason))
        }
    }

    function _wrap(address weth, uint amount) internal {
        IWETH(weth).deposit{ value: amount }();
    }

    function _approveTokenSpendingIfNeeded(address token, address spender) internal {
        if (IERC20(token).allowance(address(this), spender) == 0) {
            token.safeApprove(spender, type(uint).max);
        }
    }

    function _prepareToSwap(
        address inputToken,
        uint inputAmount,
        address _router
    ) internal {
        IERC20(inputToken).safeTransferFrom(msg.sender, address(this), inputAmount);
        _approveTokenSpendingIfNeeded(inputToken, _router);
    }

    function _sweepTokensTo(address token, address zapRecipient) internal returns (uint sweptAmount) {
        sweptAmount = _sweepTokensTo(token, zapRecipient, false);
    }

    function _sweepTokensTo(
        address token,
        address zapRecipient,
        bool revertOnSweepAmountZero
    ) internal returns (uint sweptAmount) {
        sweptAmount = IERC20(token).balanceOf(address(this));
        if (sweptAmount == 0 && revertOnSweepAmountZero) {
            revert SweepAmountZero();
        }

        if (sweptAmount > 0) {
            IERC20(token).safeTransfer(zapRecipient, sweptAmount);
        }
    }
}

File 14 of 14 : BaseSolidZapStaker.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.18;

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "../../interfaces/liquidity-deployer/IHypervisor.sol";
import "../../interfaces/liquidity-deployer/IUniProxy.sol";
import "../../interfaces/staking/ISolidStakingActions_0_8_18.sol";
import "../BaseZap.sol";

/// @author Solid World
abstract contract BaseSolidZapStaker is BaseZap, ISolidZapStaker, ReentrancyGuard {
    address public immutable router;
    address public immutable weth;
    address public immutable solidStaking;

    constructor(
        address _router,
        address _weth,
        address _solidStaking
    ) {
        router = _router;
        weth = _weth;
        solidStaking = _solidStaking;

        IWETH(weth).approve(_router, type(uint).max);
    }

    function _fetchHypervisorTokens(address hypervisor)
        internal
        view
        returns (address token0, address token1)
    {
        token0 = IHypervisor(hypervisor).token0();
        token1 = IHypervisor(hypervisor).token1();
    }

    function _fetchTokenBalances(address token0, address token1)
        internal
        view
        returns (uint token0Balance, uint token1Balance)
    {
        token0Balance = IERC20(token0).balanceOf(address(this));
        token1Balance = IERC20(token1).balanceOf(address(this));
    }

    function _deployLiquidity(SwapResults memory swapResults, address hypervisor)
        internal
        returns (uint shares)
    {
        _approveTokenSpendingIfNeeded(swapResults.token0._address, hypervisor);
        _approveTokenSpendingIfNeeded(swapResults.token1._address, hypervisor);
        shares = IUniProxy(getUniProxy(hypervisor)).deposit(
            swapResults.token0.balance,
            swapResults.token1.balance,
            address(this),
            hypervisor,
            _uniProxyMinIn()
        );
    }

    function _stakeWithRecipient(
        address token,
        uint amount,
        address zapRecipient
    ) internal {
        ISolidStakingActions(solidStaking).stake(token, amount, zapRecipient);
    }

    function _between(
        uint x,
        uint min,
        uint max
    ) internal pure returns (bool) {
        return x >= min && x <= max;
    }

    function _uniProxyMinIn() internal pure returns (uint[4] memory) {
        return [uint(0), uint(0), uint(0), uint(0)];
    }

    function getUniProxy(address hypervisor) internal view returns (address) {
        return IHypervisor(hypervisor).whitelistedAddress();
    }
}

Settings
{
  "evmVersion": "paris",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_weth","type":"address"},{"internalType":"address","name":"_solidStaking","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"acquired","type":"uint256"},{"internalType":"uint256","name":"min","type":"uint256"}],"name":"AcquiredSharesLessThanMin","type":"error"},{"inputs":[],"name":"GenericSwapError","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidSwap","type":"error"},{"inputs":[],"name":"SweepAmountZero","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"zapRecipient","type":"address"},{"indexed":true,"internalType":"address","name":"inputToken","type":"address"},{"indexed":true,"internalType":"uint256","name":"inputAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"ZapStake","type":"event"},{"inputs":[],"name":"router","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"hypervisor","type":"address"},{"internalType":"bytes","name":"swap1","type":"bytes"},{"internalType":"bytes","name":"swap2","type":"bytes"}],"name":"simulateStakeDoubleSwap","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"},{"components":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"internalType":"struct ISolidZapStaker.Fraction","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"hypervisor","type":"address"},{"internalType":"bytes","name":"swap1","type":"bytes"},{"internalType":"bytes","name":"swap2","type":"bytes"}],"name":"simulateStakeETH","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"},{"components":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"internalType":"struct ISolidZapStaker.Fraction","name":"","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"hypervisor","type":"address"},{"internalType":"bytes","name":"swap","type":"bytes"}],"name":"simulateStakeSingleSwap","outputs":[{"internalType":"bool","name":"isDustless","type":"bool"},{"internalType":"uint256","name":"shares","type":"uint256"},{"components":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"internalType":"struct ISolidZapStaker.Fraction","name":"ratio","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"solidStaking","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"hypervisor","type":"address"},{"internalType":"bytes","name":"swap1","type":"bytes"},{"internalType":"bytes","name":"swap2","type":"bytes"},{"internalType":"uint256","name":"minShares","type":"uint256"}],"name":"stakeDoubleSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"hypervisor","type":"address"},{"internalType":"bytes","name":"swap1","type":"bytes"},{"internalType":"bytes","name":"swap2","type":"bytes"},{"internalType":"uint256","name":"minShares","type":"uint256"},{"internalType":"address","name":"zapRecipient","type":"address"}],"name":"stakeDoubleSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"hypervisor","type":"address"},{"internalType":"bytes","name":"swap1","type":"bytes"},{"internalType":"bytes","name":"swap2","type":"bytes"},{"internalType":"uint256","name":"minShares","type":"uint256"},{"internalType":"address","name":"zapRecipient","type":"address"}],"name":"stakeETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"hypervisor","type":"address"},{"internalType":"bytes","name":"swap1","type":"bytes"},{"internalType":"bytes","name":"swap2","type":"bytes"},{"internalType":"uint256","name":"minShares","type":"uint256"}],"name":"stakeETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"hypervisor","type":"address"},{"internalType":"bytes","name":"swap","type":"bytes"},{"internalType":"uint256","name":"minShares","type":"uint256"},{"internalType":"address","name":"zapRecipient","type":"address"}],"name":"stakeSingleSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"hypervisor","type":"address"},{"internalType":"bytes","name":"swap","type":"bytes"},{"internalType":"uint256","name":"minShares","type":"uint256"}],"name":"stakeSingleSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60e06040523480156200001157600080fd5b5060405162001e2d38038062001e2d8339810160408190526200003491620000f4565b60016000556001600160a01b03838116608081905283821660a081905291831660c05260405163095ea7b360e01b8152600481019190915260001960248201528491849184919063095ea7b3906044016020604051808303816000875af1158015620000a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ca91906200013e565b5050505050505062000169565b80516001600160a01b0381168114620000ef57600080fd5b919050565b6000806000606084860312156200010a57600080fd5b6200011584620000d7565b92506200012560208501620000d7565b91506200013560408501620000d7565b90509250925092565b6000602082840312156200015157600080fd5b815180151581146200016257600080fd5b9392505050565b60805160a05160c051611c39620001f4600039600081816101e401528181610c8d01526113a501526000818161018b0152818161032d015281816103570152818161048c015281816104e8015261051201526000818161027e015281816102d1015281816103c9015281816105a301528181610895015281816108be0152610c0f0152611c396000f3fe6080604052600436106100c75760003560e01c80634d93907211610074578063c0dd9c2f1161004e578063c0dd9c2f1461024c578063f887ea401461026c578063fbe522d4146102a057600080fd5b80634d939072146102065780637ead4aa414610226578063b998ef0e1461023957600080fd5b806310241b93116100a557806310241b93146101595780633fc8cef314610179578063452b7724146101d257600080fd5b806303df8699146100cc57806307e1761a146100ff5780630e8807dc14610112575b600080fd5b3480156100d857600080fd5b506100ec6100e7366004611596565b6102c0565b6040519081526020015b60405180910390f35b6100ec61010d36600461163c565b61031e565b34801561011e57600080fd5b5061013261012d3660046116dc565b61039a565b604080519315158452602080850193909352815190840152015160608201526080016100f6565b34801561016557600080fd5b506100ec61017436600461177b565b610417565b34801561018557600080fd5b506101ad7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f6565b3480156101de57600080fd5b506101ad7f000000000000000000000000000000000000000000000000000000000000000081565b34801561021257600080fd5b506100ec6102213660046117fb565b610430565b610132610234366004611876565b61045f565b6100ec6102473660046118f9565b6104d9565b34801561025857600080fd5b50610132610267366004611984565b61053e565b34801561027857600080fd5b506101ad7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102ac57600080fd5b506100ec6102bb3660046119e6565b610592565b60006102ca6105f1565b6102f589897f0000000000000000000000000000000000000000000000000000000000000000610669565b61030689898989898989893361069a565b90506103126001600055565b98975050505050505050565b60006103286105f1565b6103527f0000000000000000000000000000000000000000000000000000000000000000346106c9565b6103837f0000000000000000000000000000000000000000000000000000000000000000348a8a8a8a8a8a8a61069a565b905061038f6001600055565b979650505050505050565b6000806103ba604051806040016040528060008152602001600081525090565b6103c26105f1565b6103ed8a8a7f0000000000000000000000000000000000000000000000000000000000000000610669565b6103fa888888888861072e565b92509250925061040a6001600055565b9750975097945050505050565b60006104216105f1565b6103838888888888888861077b565b600061043a6105f1565b6104498787878787873361077b565b90506104556001600055565b9695505050505050565b60008061047f604051806040016040528060008152602001600081525090565b6104876105f1565b6104b17f0000000000000000000000000000000000000000000000000000000000000000346106c9565b6104be888888888861072e565b9250925092506104ce6001600055565b955095509592505050565b60006104e36105f1565b61050d7f0000000000000000000000000000000000000000000000000000000000000000346106c9565b6104497f0000000000000000000000000000000000000000000000000000000000000000348989898989893361069a565b60008061055e604051806040016040528060008152602001600081525090565b6105666105f1565b6000610575898989898961079b565b905061058187826109a9565b935093509350506104ce6001600055565b600061059c6105f1565b6105c78a8a7f0000000000000000000000000000000000000000000000000000000000000000610669565b6105d88a8a8a8a8a8a8a8a8a61069a565b90506105e46001600055565b9998505050505050505050565b600260005403610662576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600055565b61068b73ffffffffffffffffffffffffffffffffffffffff84163330856109f2565b6106958382610ad4565b505050565b6000806106aa8989898989610bb6565b90506106ba8b8b8b878786610c35565b9b9a5050505050505050505050565b8173ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561071157600080fd5b505af1158015610725573d6000803e3d6000fd5b50505050505050565b60008061074e604051806040016040528060008152602001600081525090565b600061075d8989898989610bb6565b905061076989826109a9565b93509350935050955095509592505050565b60008061078b898989898961079b565b90506105e4898989878786610c35565b6040805160808101825260008183018181526060830182905282528251808401909352808352602080840182905282019290925290806107da86610d2e565b915091508173ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415801561084657508073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614155b1561087d576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008061088a8484610e18565b915091506108b98a8a7f0000000000000000000000000000000000000000000000000000000000000000610669565b6108e47f00000000000000000000000000000000000000000000000000000000000000008888610f45565b6000806108f18686610e18565b9150915083821115806109045750828111155b1561093b576040517f1115766700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865173ffffffffffffffffffffffffffffffffffffffff871690526109608483611ad0565b875160209081019190915287015173ffffffffffffffffffffffffffffffffffffffff861690526109918382611ad0565b602080890151015250949a9950505050505050505050565b6000806109c9604051806040016040528060008152602001600081525090565b6109d38585610fc4565b909350905082156109eb576109e884866110e7565b91505b9250925092565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff8581166004840152841660248301526044820183905290600080606483828a5af1610a5d573d6000803e3d6000fd5b50610a67856111b1565b610acd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f475076323a206661696c6564207472616e7366657246726f6d000000000000006044820152606401610659565b5050505050565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff828116602483015283169063dd62ed3e90604401602060405180830381865afa158015610b46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6a9190611ae3565b600003610bb257610bb273ffffffffffffffffffffffffffffffffffffffff8316827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61127c565b5050565b604080516080810182526000818301818152606083018290528252825180840190935280835260208084018290528201929092529080610bf588610d2e565b91509150600080610c068484610e18565b915091506108b97f00000000000000000000000000000000000000000000000000000000000000008a8a610f45565b6000610c4182866110e7565b905083811015610c87576040517f19a6c71a0000000000000000000000000000000000000000000000000000000081526004810182905260248101859052604401610659565b610cb1857f0000000000000000000000000000000000000000000000000000000000000000610ad4565b610cbc858285611351565b858773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f7602444f1556ffa1306aa87f177d86fbfe2b5088a5306c38bd2d223ed1de707584604051610d1c91815260200190565b60405180910390a49695505050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da09190611afc565b91508273ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ded573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e119190611afc565b9050915091565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090819073ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa158015610e87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eab9190611ae3565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290925073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610f18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3c9190611ae3565b90509250929050565b6000808473ffffffffffffffffffffffffffffffffffffffff168484604051610f6f929190611b19565b6000604051808303816000865af19150503d8060008114610fac576040519150601f19603f3d011682016040523d82523d6000602084013e610fb1565b606091505b509150915081610acd57610acd816113e9565b6000610fe3604051806040016040528060008152602001600081525090565b600080610fef8661142c565b855180516020909101516040517f5ccfb71d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a8116600483015292831660248201526044810191909152911690635ccfb71d906064016040805180830381865afa158015611074573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110989190611b29565b915091506110af85602001516020015183836114a3565b9350836110de57604051806040016040528086600001516020015181526020016110d984846114bd565b905292505b50509250929050565b8151516000906110f79083610ad4565b6020830151516111079083610ad4565b6111108261142c565b73ffffffffffffffffffffffffffffffffffffffff16638e3c92e484600001516020015185602001516020015130866111476114d8565b6040518663ffffffff1660e01b8152600401611167959493929190611b4d565b6020604051808303816000875af1158015611186573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111aa9190611ae3565b9392505050565b60006111f0565b7f08c379a000000000000000000000000000000000000000000000000000000000600052602060045280602452508060445260646000fd5b3d801561122f57602081146112695761122a7f475076323a206d616c666f726d6564207472616e7366657220726573756c7400601f6111b8565b611276565b823b611260576112607f475076323a206e6f74206120636f6e747261637400000000000000000000000060146111b8565b60019150611276565b3d6000803e600051151591505b50919050565b60006040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061134b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610659565b50505050565b6040517f294091cd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526024820184905282811660448301527f0000000000000000000000000000000000000000000000000000000000000000169063294091cd90606401600060405180830381600087803b15801561071157600080fd5b8051600003611424576040517f67e1b70700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b60008173ffffffffffffffffffffffffffffffffffffffff166386a290816040518163ffffffff1660e01b8152600401602060405180830381865afa158015611479573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149d9190611afc565b92915050565b60008284101580156114b55750818411155b949350505050565b60006114cc6002848418611bb5565b6111aa90848416611bf0565b6114e061150a565b60405180608001604052806000815260200160008152602001600081526020016000815250905090565b60405180608001604052806004906020820280368337509192915050565b73ffffffffffffffffffffffffffffffffffffffff8116811461154a57600080fd5b50565b60008083601f84011261155f57600080fd5b50813567ffffffffffffffff81111561157757600080fd5b60208301915083602082850101111561158f57600080fd5b9250929050565b60008060008060008060008060c0898b0312156115b257600080fd5b88356115bd81611528565b97506020890135965060408901356115d481611528565b9550606089013567ffffffffffffffff808211156115f157600080fd5b6115fd8c838d0161154d565b909750955060808b013591508082111561161657600080fd5b506116238b828c0161154d565b999c989b50969995989497949560a00135949350505050565b600080600080600080600060a0888a03121561165757600080fd5b873561166281611528565b9650602088013567ffffffffffffffff8082111561167f57600080fd5b61168b8b838c0161154d565b909850965060408a01359150808211156116a457600080fd5b506116b18a828b0161154d565b9095509350506060880135915060808801356116cc81611528565b8091505092959891949750929550565b600080600080600080600060a0888a0312156116f757600080fd5b873561170281611528565b965060208801359550604088013561171981611528565b9450606088013567ffffffffffffffff8082111561173657600080fd5b6117428b838c0161154d565b909650945060808a013591508082111561175b57600080fd5b506117688a828b0161154d565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561179657600080fd5b87356117a181611528565b96506020880135955060408801356117b881611528565b9450606088013567ffffffffffffffff8111156117d457600080fd5b6117e08a828b0161154d565b9095509350506080880135915060a08801356116cc81611528565b60008060008060008060a0878903121561181457600080fd5b863561181f81611528565b955060208701359450604087013561183681611528565b9350606087013567ffffffffffffffff81111561185257600080fd5b61185e89828a0161154d565b979a9699509497949695608090950135949350505050565b60008060008060006060868803121561188e57600080fd5b853561189981611528565b9450602086013567ffffffffffffffff808211156118b657600080fd5b6118c289838a0161154d565b909650945060408801359150808211156118db57600080fd5b506118e88882890161154d565b969995985093965092949392505050565b6000806000806000806080878903121561191257600080fd5b863561191d81611528565b9550602087013567ffffffffffffffff8082111561193a57600080fd5b6119468a838b0161154d565b9097509550604089013591508082111561195f57600080fd5b5061196c89828a0161154d565b979a9699509497949695606090950135949350505050565b60008060008060006080868803121561199c57600080fd5b85356119a781611528565b94506020860135935060408601356119be81611528565b9250606086013567ffffffffffffffff8111156119da57600080fd5b6118e88882890161154d565b600080600080600080600080600060e08a8c031215611a0457600080fd5b8935611a0f81611528565b985060208a0135975060408a0135611a2681611528565b965060608a013567ffffffffffffffff80821115611a4357600080fd5b611a4f8d838e0161154d565b909850965060808c0135915080821115611a6857600080fd5b50611a758c828d0161154d565b90955093505060a08a0135915060c08a0135611a9081611528565b809150509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561149d5761149d611aa1565b600060208284031215611af557600080fd5b5051919050565b600060208284031215611b0e57600080fd5b81516111aa81611528565b8183823760009101908152919050565b60008060408385031215611b3c57600080fd5b505080516020909101519092909150565b858152602080820186905273ffffffffffffffffffffffffffffffffffffffff858116604084015284166060830152610100820190608083018460005b6004811015611ba757815183529183019190830190600101611b8a565b505050509695505050505050565b600082611beb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8082018082111561149d5761149d611aa156fea2646970667358221220f1bc86db457c1cbe43bcb11b7a861fa4adf000938b5a18965119ccec7b95822264736f6c63430008120033000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270000000000000000000000000ad7ce5cf8e594e1efc6922ab2c9f81d7a0e14337

Deployed Bytecode

0x6080604052600436106100c75760003560e01c80634d93907211610074578063c0dd9c2f1161004e578063c0dd9c2f1461024c578063f887ea401461026c578063fbe522d4146102a057600080fd5b80634d939072146102065780637ead4aa414610226578063b998ef0e1461023957600080fd5b806310241b93116100a557806310241b93146101595780633fc8cef314610179578063452b7724146101d257600080fd5b806303df8699146100cc57806307e1761a146100ff5780630e8807dc14610112575b600080fd5b3480156100d857600080fd5b506100ec6100e7366004611596565b6102c0565b6040519081526020015b60405180910390f35b6100ec61010d36600461163c565b61031e565b34801561011e57600080fd5b5061013261012d3660046116dc565b61039a565b604080519315158452602080850193909352815190840152015160608201526080016100f6565b34801561016557600080fd5b506100ec61017436600461177b565b610417565b34801561018557600080fd5b506101ad7f0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf127081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f6565b3480156101de57600080fd5b506101ad7f000000000000000000000000ad7ce5cf8e594e1efc6922ab2c9f81d7a0e1433781565b34801561021257600080fd5b506100ec6102213660046117fb565b610430565b610132610234366004611876565b61045f565b6100ec6102473660046118f9565b6104d9565b34801561025857600080fd5b50610132610267366004611984565b61053e565b34801561027857600080fd5b506101ad7f000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff81565b3480156102ac57600080fd5b506100ec6102bb3660046119e6565b610592565b60006102ca6105f1565b6102f589897f000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff610669565b61030689898989898989893361069a565b90506103126001600055565b98975050505050505050565b60006103286105f1565b6103527f0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270346106c9565b6103837f0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270348a8a8a8a8a8a8a61069a565b905061038f6001600055565b979650505050505050565b6000806103ba604051806040016040528060008152602001600081525090565b6103c26105f1565b6103ed8a8a7f000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff610669565b6103fa888888888861072e565b92509250925061040a6001600055565b9750975097945050505050565b60006104216105f1565b6103838888888888888861077b565b600061043a6105f1565b6104498787878787873361077b565b90506104556001600055565b9695505050505050565b60008061047f604051806040016040528060008152602001600081525090565b6104876105f1565b6104b17f0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270346106c9565b6104be888888888861072e565b9250925092506104ce6001600055565b955095509592505050565b60006104e36105f1565b61050d7f0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270346106c9565b6104497f0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270348989898989893361069a565b60008061055e604051806040016040528060008152602001600081525090565b6105666105f1565b6000610575898989898961079b565b905061058187826109a9565b935093509350506104ce6001600055565b600061059c6105f1565b6105c78a8a7f000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff610669565b6105d88a8a8a8a8a8a8a8a8a61069a565b90506105e46001600055565b9998505050505050505050565b600260005403610662576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002600055565b61068b73ffffffffffffffffffffffffffffffffffffffff84163330856109f2565b6106958382610ad4565b505050565b6000806106aa8989898989610bb6565b90506106ba8b8b8b878786610c35565b9b9a5050505050505050505050565b8173ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561071157600080fd5b505af1158015610725573d6000803e3d6000fd5b50505050505050565b60008061074e604051806040016040528060008152602001600081525090565b600061075d8989898989610bb6565b905061076989826109a9565b93509350935050955095509592505050565b60008061078b898989898961079b565b90506105e4898989878786610c35565b6040805160808101825260008183018181526060830182905282528251808401909352808352602080840182905282019290925290806107da86610d2e565b915091508173ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415801561084657508073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614155b1561087d576040517fb4fa3fb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008061088a8484610e18565b915091506108b98a8a7f000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff610669565b6108e47f000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff8888610f45565b6000806108f18686610e18565b9150915083821115806109045750828111155b1561093b576040517f1115766700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865173ffffffffffffffffffffffffffffffffffffffff871690526109608483611ad0565b875160209081019190915287015173ffffffffffffffffffffffffffffffffffffffff861690526109918382611ad0565b602080890151015250949a9950505050505050505050565b6000806109c9604051806040016040528060008152602001600081525090565b6109d38585610fc4565b909350905082156109eb576109e884866110e7565b91505b9250925092565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff8581166004840152841660248301526044820183905290600080606483828a5af1610a5d573d6000803e3d6000fd5b50610a67856111b1565b610acd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f475076323a206661696c6564207472616e7366657246726f6d000000000000006044820152606401610659565b5050505050565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff828116602483015283169063dd62ed3e90604401602060405180830381865afa158015610b46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6a9190611ae3565b600003610bb257610bb273ffffffffffffffffffffffffffffffffffffffff8316827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61127c565b5050565b604080516080810182526000818301818152606083018290528252825180840190935280835260208084018290528201929092529080610bf588610d2e565b91509150600080610c068484610e18565b915091506108b97f000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff8a8a610f45565b6000610c4182866110e7565b905083811015610c87576040517f19a6c71a0000000000000000000000000000000000000000000000000000000081526004810182905260248101859052604401610659565b610cb1857f000000000000000000000000ad7ce5cf8e594e1efc6922ab2c9f81d7a0e14337610ad4565b610cbc858285611351565b858773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f7602444f1556ffa1306aa87f177d86fbfe2b5088a5306c38bd2d223ed1de707584604051610d1c91815260200190565b60405180910390a49695505050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da09190611afc565b91508273ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ded573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e119190611afc565b9050915091565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090819073ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa158015610e87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eab9190611ae3565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290925073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610f18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3c9190611ae3565b90509250929050565b6000808473ffffffffffffffffffffffffffffffffffffffff168484604051610f6f929190611b19565b6000604051808303816000865af19150503d8060008114610fac576040519150601f19603f3d011682016040523d82523d6000602084013e610fb1565b606091505b509150915081610acd57610acd816113e9565b6000610fe3604051806040016040528060008152602001600081525090565b600080610fef8661142c565b855180516020909101516040517f5ccfb71d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a8116600483015292831660248201526044810191909152911690635ccfb71d906064016040805180830381865afa158015611074573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110989190611b29565b915091506110af85602001516020015183836114a3565b9350836110de57604051806040016040528086600001516020015181526020016110d984846114bd565b905292505b50509250929050565b8151516000906110f79083610ad4565b6020830151516111079083610ad4565b6111108261142c565b73ffffffffffffffffffffffffffffffffffffffff16638e3c92e484600001516020015185602001516020015130866111476114d8565b6040518663ffffffff1660e01b8152600401611167959493929190611b4d565b6020604051808303816000875af1158015611186573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111aa9190611ae3565b9392505050565b60006111f0565b7f08c379a000000000000000000000000000000000000000000000000000000000600052602060045280602452508060445260646000fd5b3d801561122f57602081146112695761122a7f475076323a206d616c666f726d6564207472616e7366657220726573756c7400601f6111b8565b611276565b823b611260576112607f475076323a206e6f74206120636f6e747261637400000000000000000000000060146111b8565b60019150611276565b3d6000803e600051151591505b50919050565b60006040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061134b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610659565b50505050565b6040517f294091cd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301526024820184905282811660448301527f000000000000000000000000ad7ce5cf8e594e1efc6922ab2c9f81d7a0e14337169063294091cd90606401600060405180830381600087803b15801561071157600080fd5b8051600003611424576040517f67e1b70700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b60008173ffffffffffffffffffffffffffffffffffffffff166386a290816040518163ffffffff1660e01b8152600401602060405180830381865afa158015611479573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149d9190611afc565b92915050565b60008284101580156114b55750818411155b949350505050565b60006114cc6002848418611bb5565b6111aa90848416611bf0565b6114e061150a565b60405180608001604052806000815260200160008152602001600081526020016000815250905090565b60405180608001604052806004906020820280368337509192915050565b73ffffffffffffffffffffffffffffffffffffffff8116811461154a57600080fd5b50565b60008083601f84011261155f57600080fd5b50813567ffffffffffffffff81111561157757600080fd5b60208301915083602082850101111561158f57600080fd5b9250929050565b60008060008060008060008060c0898b0312156115b257600080fd5b88356115bd81611528565b97506020890135965060408901356115d481611528565b9550606089013567ffffffffffffffff808211156115f157600080fd5b6115fd8c838d0161154d565b909750955060808b013591508082111561161657600080fd5b506116238b828c0161154d565b999c989b50969995989497949560a00135949350505050565b600080600080600080600060a0888a03121561165757600080fd5b873561166281611528565b9650602088013567ffffffffffffffff8082111561167f57600080fd5b61168b8b838c0161154d565b909850965060408a01359150808211156116a457600080fd5b506116b18a828b0161154d565b9095509350506060880135915060808801356116cc81611528565b8091505092959891949750929550565b600080600080600080600060a0888a0312156116f757600080fd5b873561170281611528565b965060208801359550604088013561171981611528565b9450606088013567ffffffffffffffff8082111561173657600080fd5b6117428b838c0161154d565b909650945060808a013591508082111561175b57600080fd5b506117688a828b0161154d565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561179657600080fd5b87356117a181611528565b96506020880135955060408801356117b881611528565b9450606088013567ffffffffffffffff8111156117d457600080fd5b6117e08a828b0161154d565b9095509350506080880135915060a08801356116cc81611528565b60008060008060008060a0878903121561181457600080fd5b863561181f81611528565b955060208701359450604087013561183681611528565b9350606087013567ffffffffffffffff81111561185257600080fd5b61185e89828a0161154d565b979a9699509497949695608090950135949350505050565b60008060008060006060868803121561188e57600080fd5b853561189981611528565b9450602086013567ffffffffffffffff808211156118b657600080fd5b6118c289838a0161154d565b909650945060408801359150808211156118db57600080fd5b506118e88882890161154d565b969995985093965092949392505050565b6000806000806000806080878903121561191257600080fd5b863561191d81611528565b9550602087013567ffffffffffffffff8082111561193a57600080fd5b6119468a838b0161154d565b9097509550604089013591508082111561195f57600080fd5b5061196c89828a0161154d565b979a9699509497949695606090950135949350505050565b60008060008060006080868803121561199c57600080fd5b85356119a781611528565b94506020860135935060408601356119be81611528565b9250606086013567ffffffffffffffff8111156119da57600080fd5b6118e88882890161154d565b600080600080600080600080600060e08a8c031215611a0457600080fd5b8935611a0f81611528565b985060208a0135975060408a0135611a2681611528565b965060608a013567ffffffffffffffff80821115611a4357600080fd5b611a4f8d838e0161154d565b909850965060808c0135915080821115611a6857600080fd5b50611a758c828d0161154d565b90955093505060a08a0135915060c08a0135611a9081611528565b809150509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561149d5761149d611aa1565b600060208284031215611af557600080fd5b5051919050565b600060208284031215611b0e57600080fd5b81516111aa81611528565b8183823760009101908152919050565b60008060408385031215611b3c57600080fd5b505080516020909101519092909150565b858152602080820186905273ffffffffffffffffffffffffffffffffffffffff858116604084015284166060830152610100820190608083018460005b6004811015611ba757815183529183019190830190600101611b8a565b505050509695505050505050565b600082611beb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8082018082111561149d5761149d611aa156fea2646970667358221220f1bc86db457c1cbe43bcb11b7a861fa4adf000938b5a18965119ccec7b95822264736f6c63430008120033

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

000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270000000000000000000000000ad7ce5cf8e594e1efc6922ab2c9f81d7a0e14337

-----Decoded View---------------
Arg [0] : _router (address): 0xDef1C0ded9bec7F1a1670819833240f027b25EfF
Arg [1] : _weth (address): 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270
Arg [2] : _solidStaking (address): 0xaD7Ce5Cf8E594e1EFC6922Ab2c9F81d7a0E14337

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000def1c0ded9bec7f1a1670819833240f027b25eff
Arg [1] : 0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270
Arg [2] : 000000000000000000000000ad7ce5cf8e594e1efc6922ab2c9f81d7a0e14337


Block Transaction Gas Used Reward
view all blocks produced

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

OVERVIEW

This smart contract enables one-click staking into Solid World, by allowing users to start with any token, swap it into the correct pair, deposit for LP tokens via Gamma.xyz, and stake these LP tokens, all in 1-2 transactions. It uses external dependencies like DEX aggregators and Gamma ...

Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.