ETH Price: $2,356.08 (+0.10%)
Gas: 46 Gwei

Contract

0x1f2d51eadf24BfcC6Eeb8318D0408dFD9Fbd05d9
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Sponsored

Transaction Hash
Method
Block
From
To
Value
Approve142603462022-02-23 5:04:27655 days 15 hrs ago1645592667IN
mStable: Save Wrapper
0 ETH0.0228412865.3
Approve142602442022-02-23 4:40:21655 days 15 hrs ago1645591221IN
mStable: Save Wrapper
0 ETH0.0299898564.5
0x60a06040142553962022-02-22 10:44:43656 days 9 hrs ago1645526683IN
 Create: SaveWrapper
0 ETH0.0818786243.8

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SaveWrapper

Compiler Version
v0.8.6+commit.11564f7e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 14 : SaveWrapper.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.6;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import { IBoostedVaultWithLockup } from "../../interfaces/IBoostedVaultWithLockup.sol";
import { IFeederPool } from "../../interfaces/IFeederPool.sol";
import { IMasset } from "../../interfaces/IMasset.sol";
import { ISavingsContractV3 } from "../../interfaces/ISavingsContract.sol";
import { IUniswapV2Router02 } from "../../peripheral/Uniswap/IUniswapV2Router02.sol";
import { IBasicToken } from "../../shared/IBasicToken.sol";
import { ImmutableModule } from "../../shared/ImmutableModule.sol";

// FLOWS
// 0 - mAsset -> Savings Vault
// 1 - bAsset -> Save/Savings Vault via Mint
// 2 - fAsset -> Save/Savings Vault via Feeder Pool
// 3 - ETH    -> Save/Savings Vault via Uniswap
contract SaveWrapper is ImmutableModule {
    using SafeERC20 for IERC20;

    constructor(address _nexus) ImmutableModule(_nexus) {}

    /**
     * @dev 0. Simply saves an mAsset and then into the vault
     * @param _mAsset   mAsset address
     * @param _save     Save address
     * @param _vault    Boosted Savings Vault address
     * @param _amount   Units of mAsset to deposit to savings
     */
    function saveAndStake(
        address _mAsset,
        address _save,
        address _vault,
        uint256 _amount
    ) external {
        _saveAndStake(_mAsset, _save, _vault, _amount, true, address(0));
    }

    /**
     * @dev 0. Simply saves an mAsset and then into the vault
     * @param _mAsset   mAsset address
     * @param _save     Save address
     * @param _vault    Boosted Savings Vault address
     * @param _amount   Units of mAsset to deposit to savings
     * @param _referrer Referrer address for this deposit.
     */
    function saveAndStake(
        address _mAsset,
        address _save,
        address _vault,
        uint256 _amount,
        address _referrer
    ) external {
        _saveAndStake(_mAsset, _save, _vault, _amount, true, _referrer);
    }

    /**
     * @dev 1. Mints an mAsset and then deposits to Save/Savings Vault
     * @param _mAsset       mAsset address
     * @param _bAsset       bAsset address
     * @param _save         Save address
     * @param _vault        Boosted Savings Vault address
     * @param _amount       Amount of bAsset to mint with
     * @param _minOut       Min amount of mAsset to get back
     * @param _stake        Add the imAsset to the Boosted Savings Vault?
     */
    function saveViaMint(
        address _mAsset,
        address _save,
        address _vault,
        address _bAsset,
        uint256 _amount,
        uint256 _minOut,
        bool _stake
    ) external {
        _saveViaMint(_mAsset, _save, _vault, _bAsset, _amount, _minOut, _stake, address(0));
    }

    /**
     * @dev 1. Mints an mAsset and then deposits to Save/Savings Vault
     * @param _mAsset       mAsset address
     * @param _bAsset       bAsset address
     * @param _save         Save address
     * @param _vault        Boosted Savings Vault address
     * @param _amount       Amount of bAsset to mint with
     * @param _minOut       Min amount of mAsset to get back
     * @param _stake        Add the imAsset to the Boosted Savings Vault?
     * @param _referrer     Referrer address for this deposit.
     */
    function saveViaMint(
        address _mAsset,
        address _save,
        address _vault,
        address _bAsset,
        uint256 _amount,
        uint256 _minOut,
        bool _stake,
        address _referrer
    ) external {
        _saveViaMint(_mAsset, _save, _vault, _bAsset, _amount, _minOut, _stake, _referrer);
    }

    /**
     * @dev 2. Swaps fAsset for mAsset and then deposits to Save/Savings Vault
     * @param _mAsset             mAsset address
     * @param _save               Save address
     * @param _vault              Boosted Savings Vault address
     * @param _feeder             Feeder Pool address
     * @param _fAsset             fAsset address
     * @param _fAssetQuantity     Quantity of fAsset sent
     * @param _minOutputQuantity  Min amount of mAsset to be swapped and deposited
     * @param _stake              Deposit the imAsset in the Savings Vault?
     */
    function saveViaSwap(
        address _mAsset,
        address _save,
        address _vault,
        address _feeder,
        address _fAsset,
        uint256 _fAssetQuantity,
        uint256 _minOutputQuantity,
        bool _stake
    ) external {
        _saveViaSwap(
            _mAsset,
            _save,
            _vault,
            _feeder,
            _fAsset,
            _fAssetQuantity,
            _minOutputQuantity,
            _stake,
            address(0)
        );
    }

    /**
     * @dev 2. Swaps fAsset for mAsset and then deposits to Save/Savings Vault
     * @param _mAsset             mAsset address
     * @param _save               Save address
     * @param _vault              Boosted Savings Vault address
     * @param _feeder             Feeder Pool address
     * @param _fAsset             fAsset address
     * @param _fAssetQuantity     Quantity of fAsset sent
     * @param _minOutputQuantity  Min amount of mAsset to be swapped and deposited
     * @param _stake              Deposit the imAsset in the Savings Vault?
     * @param _referrer       Referrer address for this deposit.
     */
    function saveViaSwap(
        address _mAsset,
        address _save,
        address _vault,
        address _feeder,
        address _fAsset,
        uint256 _fAssetQuantity,
        uint256 _minOutputQuantity,
        bool _stake,
        address _referrer
    ) external {
        _saveViaSwap(
            _mAsset,
            _save,
            _vault,
            _feeder,
            _fAsset,
            _fAssetQuantity,
            _minOutputQuantity,
            _stake,
            _referrer
        );
    }

    /**
     * @dev 3. Buys a bAsset on Uniswap with ETH, then mints imAsset via mAsset,
     *         optionally staking in the Boosted Savings Vault
     * @param _mAsset         mAsset address
     * @param _save           Save address
     * @param _vault          Boosted vault address
     * @param _uniswap        Uniswap router address
     * @param _amountOutMin   Min uniswap output in bAsset units
     * @param _path           Sell path on Uniswap (e.g. [WETH, DAI])
     * @param _minOutMStable  Min amount of mAsset to receive
     * @param _stake          Add the imAsset to the Savings Vault?
     */
    function saveViaUniswapETH(
        address _mAsset,
        address _save,
        address _vault,
        address _uniswap,
        uint256 _amountOutMin,
        address[] calldata _path,
        uint256 _minOutMStable,
        bool _stake
    ) external payable {
        _saveViaUniswapETH(
            _mAsset,
            _save,
            _vault,
            _uniswap,
            _amountOutMin,
            _path,
            _minOutMStable,
            _stake,
            address(0)
        );
    }

    /**
     * @dev 3. Buys a bAsset on Uniswap with ETH, then mints imAsset via mAsset,
     *         optionally staking in the Boosted Savings Vault
     * @param _mAsset         mAsset address
     * @param _save           Save address
     * @param _vault          Boosted vault address
     * @param _uniswap        Uniswap router address
     * @param _amountOutMin   Min uniswap output in bAsset units
     * @param _path           Sell path on Uniswap (e.g. [WETH, DAI])
     * @param _minOutMStable  Min amount of mAsset to receive
     * @param _stake          Add the imAsset to the Savings Vault?
     * @param _referrer       Referrer address for this deposit.
     */
    function saveViaUniswapETH(
        address _mAsset,
        address _save,
        address _vault,
        address _uniswap,
        uint256 _amountOutMin,
        address[] calldata _path,
        uint256 _minOutMStable,
        bool _stake,
        address _referrer
    ) external payable {
        _saveViaUniswapETH(
            _mAsset,
            _save,
            _vault,
            _uniswap,
            _amountOutMin,
            _path,
            _minOutMStable,
            _stake,
            _referrer
        );
    }

    /**
     * @dev Gets estimated mAsset output from a WETH > bAsset > mAsset trade
     * @param _mAsset       mAsset address
     * @param _uniswap      Uniswap router address
     * @param _ethAmount    ETH amount to sell
     * @param _path         Sell path on Uniswap (e.g. [WETH, DAI])
     */
    function estimate_saveViaUniswapETH(
        address _mAsset,
        address _uniswap,
        uint256 _ethAmount,
        address[] calldata _path
    ) external view returns (uint256 out) {
        require(_mAsset != address(0), "Invalid mAsset");
        require(_uniswap != address(0), "Invalid uniswap");

        uint256 estimatedBasset = _getAmountOut(_uniswap, _ethAmount, _path);
        return IMasset(_mAsset).getMintOutput(_path[_path.length - 1], estimatedBasset);
    }

    /**
     * @dev 0. Simply saves an mAsset and then into the vault
     * @param _mAsset   mAsset address
     * @param _save     Save address
     * @param _vault    Boosted Savings Vault address
     * @param _amount   Units of mAsset to deposit to savings
     * @param _referrer Referrer address for this deposit.
     */
    function _saveAndStake(
        address _mAsset,
        address _save,
        address _vault,
        uint256 _amount,
        bool _stake,
        address _referrer
    ) internal {
        require(_mAsset != address(0), "Invalid mAsset");
        require(_save != address(0), "Invalid save");
        require(_vault != address(0), "Invalid vault");

        // 1. Get the input mAsset
        IERC20(_mAsset).safeTransferFrom(msg.sender, address(this), _amount);

        // 2. Mint imAsset and stake in vault
        _depositAndStake(_save, _vault, _amount, _stake, _referrer);
    }

    /** @dev Internal func to deposit into Save and optionally stake in the vault
     * @param _save       Save address
     * @param _vault      Boosted vault address
     * @param _amount     Amount of mAsset to deposit
     * @param _stake      Add the imAsset to the Savings Vault?
     * @param _referrer   Referrer address for this deposit, if any.
     */
    function _depositAndStake(
        address _save,
        address _vault,
        uint256 _amount,
        bool _stake,
        address _referrer
    ) internal {
        if (_stake && _referrer != address(0)) {
            uint256 credits = ISavingsContractV3(_save).depositSavings(
                _amount,
                address(this),
                _referrer
            );
            IBoostedVaultWithLockup(_vault).stake(msg.sender, credits);
        } else if (_stake && _referrer == address(0)) {
            uint256 credits = ISavingsContractV3(_save).depositSavings(_amount, address(this));
            IBoostedVaultWithLockup(_vault).stake(msg.sender, credits);
        } else if (!_stake && _referrer != address(0)) {
            ISavingsContractV3(_save).depositSavings(_amount, msg.sender, _referrer);
        } else {
            ISavingsContractV3(_save).depositSavings(_amount, msg.sender);
        }
    }

    /**
     * @dev 1. Mints an mAsset and then deposits to Save/Savings Vault
     * @param _mAsset       mAsset address
     * @param _bAsset       bAsset address
     * @param _save         Save address
     * @param _vault        Boosted Savings Vault address
     * @param _amount       Amount of bAsset to mint with
     * @param _minOut       Min amount of mAsset to get back
     * @param _stake        Add the imAsset to the Boosted Savings Vault?
     * @param _referrer     Referrer address for this deposit.
     */
    function _saveViaMint(
        address _mAsset,
        address _save,
        address _vault,
        address _bAsset,
        uint256 _amount,
        uint256 _minOut,
        bool _stake,
        address _referrer
    ) internal {
        require(_mAsset != address(0), "Invalid mAsset");
        require(_save != address(0), "Invalid save");
        require(_vault != address(0), "Invalid vault");
        require(_bAsset != address(0), "Invalid bAsset");

        // 1. Get the input bAsset
        IERC20(_bAsset).safeTransferFrom(msg.sender, address(this), _amount);

        // 2. Mint
        uint256 massetsMinted = IMasset(_mAsset).mint(_bAsset, _amount, _minOut, address(this));

        // 3. Mint imAsset and optionally stake in vault
        _depositAndStake(_save, _vault, massetsMinted, _stake, _referrer);
    }

    /**
     * @dev 2. Swaps fAsset for mAsset and then deposits to Save/Savings Vault
     * @param _mAsset             mAsset address
     * @param _save               Save address
     * @param _vault              Boosted Savings Vault address
     * @param _feeder             Feeder Pool address
     * @param _fAsset             fAsset address
     * @param _fAssetQuantity     Quantity of fAsset sent
     * @param _minOutputQuantity  Min amount of mAsset to be swapped and deposited
     * @param _stake              Deposit the imAsset in the Savings Vault?
     * @param _referrer           Referrer address for this deposit.
     */
    function _saveViaSwap(
        address _mAsset,
        address _save,
        address _vault,
        address _feeder,
        address _fAsset,
        uint256 _fAssetQuantity,
        uint256 _minOutputQuantity,
        bool _stake,
        address _referrer
    ) internal {
        require(_feeder != address(0), "Invalid feeder");
        require(_mAsset != address(0), "Invalid mAsset");
        require(_save != address(0), "Invalid save");
        require(_vault != address(0), "Invalid vault");
        require(_fAsset != address(0), "Invalid input");

        // 0. Transfer the fAsset here
        IERC20(_fAsset).safeTransferFrom(msg.sender, address(this), _fAssetQuantity);

        // 1. Swap the fAsset for mAsset with the feeder pool
        uint256 mAssetQuantity = IFeederPool(_feeder).swap(
            _fAsset,
            _mAsset,
            _fAssetQuantity,
            _minOutputQuantity,
            address(this)
        );

        // 2. Deposit the mAsset into Save and optionally stake in the vault
        _depositAndStake(_save, _vault, mAssetQuantity, _stake, _referrer);
    }

    /**
     * @dev 3. Buys a bAsset on Uniswap with ETH, then mints imAsset via mAsset,
     *         optionally staking in the Boosted Savings Vault
     * @param _mAsset         mAsset address
     * @param _save           Save address
     * @param _vault          Boosted vault address
     * @param _uniswap        Uniswap router address
     * @param _amountOutMin   Min uniswap output in bAsset units
     * @param _path           Sell path on Uniswap (e.g. [WETH, DAI])
     * @param _minOutMStable  Min amount of mAsset to receive
     * @param _stake          Add the imAsset to the Savings Vault?
     * @param _referrer       Referrer address for this deposit.
     */
    function _saveViaUniswapETH(
        address _mAsset,
        address _save,
        address _vault,
        address _uniswap,
        uint256 _amountOutMin,
        address[] calldata _path,
        uint256 _minOutMStable,
        bool _stake,
        address _referrer
    ) internal {
        require(_mAsset != address(0), "Invalid mAsset");
        require(_save != address(0), "Invalid save");
        require(_vault != address(0), "Invalid vault");
        require(_uniswap != address(0), "Invalid uniswap");

        // 1. Get the bAsset
        uint256[] memory amounts = IUniswapV2Router02(_uniswap).swapExactETHForTokens{
            value: msg.value
        }(_amountOutMin, _path, address(this), block.timestamp + 1000);

        // 2. Purchase mAsset
        uint256 massetsMinted = IMasset(_mAsset).mint(
            _path[_path.length - 1],
            amounts[amounts.length - 1],
            _minOutMStable,
            address(this)
        );

        // 3. Mint imAsset and optionally stake in vault
        _depositAndStake(_save, _vault, massetsMinted, _stake, _referrer);
    }

    /** @dev Internal func to get estimated Uniswap output from WETH to token trade */
    function _getAmountOut(
        address _uniswap,
        uint256 _amountIn,
        address[] memory _path
    ) internal view returns (uint256) {
        uint256[] memory amountsOut = IUniswapV2Router02(_uniswap).getAmountsOut(_amountIn, _path);
        return amountsOut[amountsOut.length - 1];
    }

    /**
     * @dev Approve mAsset and bAssets, Feeder Pools and fAssets, and Save/vault
     */
    function approve(
        address _mAsset,
        address[] calldata _bAssets,
        address[] calldata _fPools,
        address[] calldata _fAssets,
        address _save,
        address _vault
    ) external onlyKeeperOrGovernor {
        _approve(_mAsset, _save);
        _approve(_save, _vault);
        _approve(_bAssets, _mAsset);

        require(_fPools.length == _fAssets.length, "Mismatching fPools/fAssets");
        for (uint256 i = 0; i < _fPools.length; i++) {
            _approve(_fAssets[i], _fPools[i]);
        }
    }

    /**
     * @dev Approve one token/spender
     */
    function approve(address _token, address _spender) external onlyKeeperOrGovernor {
        _approve(_token, _spender);
    }

    /**
     * @dev Approve multiple tokens/one spender
     */
    function approve(address[] calldata _tokens, address _spender) external onlyKeeperOrGovernor {
        _approve(_tokens, _spender);
    }

    function _approve(address _token, address _spender) internal {
        require(_spender != address(0), "Invalid spender");
        require(_token != address(0), "Invalid token");
        IERC20(_token).safeApprove(_spender, 2**256 - 1);
    }

    function _approve(address[] calldata _tokens, address _spender) internal {
        require(_spender != address(0), "Invalid spender");
        for (uint256 i = 0; i < _tokens.length; i++) {
            require(_tokens[i] != address(0), "Invalid token");
            IERC20(_tokens[i]).safeApprove(_spender, 2**256 - 1);
        }
    }
}

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

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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

File 3 of 14 : SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 4 of 14 : IBoostedVaultWithLockup.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.6;

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

interface IBoostedVaultWithLockup {
    /**
     * @notice Stakes a given amount of the StakingToken for the sender
     * @param _amount Units of StakingToken
     */
    function stake(uint256 _amount) external;

    /**
     * @notice Stakes a given amount of the StakingToken for a given beneficiary
     * @param _beneficiary Staked tokens are credited to this address
     * @param _amount      Units of StakingToken
     */
    function stake(address _beneficiary, uint256 _amount) external;

    /**
     * @notice Withdraws stake from pool and claims any unlocked rewards.
     * Note, this function is costly - the args for _claimRewards
     * should be determined off chain and then passed to other fn
     */
    function exit() external;

    /**
     * @notice Withdraws stake from pool and claims any unlocked rewards.
     * @param _first    Index of the first array element to claim
     * @param _last     Index of the last array element to claim
     */
    function exit(uint256 _first, uint256 _last) external;

    /**
     * @notice Withdraws given stake amount from the pool
     * @param _amount Units of the staked token to withdraw
     */
    function withdraw(uint256 _amount) external;

    /**
     * @notice Redeems staked interest-bearing asset tokens for either bAsset or fAsset tokens.
     * Withdraws a given staked amount of interest-bearing assets from the vault,
     * redeems the interest-bearing asset for the underlying mAsset and either
     * 1. Redeems the underlying mAsset tokens for bAsset tokens.
     * 2. Swaps the underlying mAsset tokens for fAsset tokens in a Feeder Pool.
     * @param _amount         Units of the staked interest-bearing asset tokens to withdraw. eg imUSD or imBTC.
     * @param _minAmountOut   Minimum units of `output` tokens to be received by the beneficiary. This is to the same decimal places as the `output` token.
     * @param _output         Asset to receive in exchange for the redeemed mAssets. This can be a bAsset or a fAsset. For example:
        - bAssets (USDC, DAI, sUSD or USDT) or fAssets (GUSD, BUSD, alUSD, FEI or RAI) for mainnet imUSD Vault.
        - bAssets (USDC, DAI or USDT) or fAsset FRAX for Polygon imUSD Vault.
        - bAssets (WBTC, sBTC or renBTC) or fAssets (HBTC or TBTCV2) for mainnet imBTC Vault.
     * @param _beneficiary    Address to send `output` tokens to.
     * @param _router         mAsset address if the `output` is a bAsset. Feeder Pool address if the `output` is a fAsset.
     * @param _isBassetOut    `true` if `output` is a bAsset. `false` if `output` is a fAsset.
     * @return outputQuantity Units of `output` tokens sent to the beneficiary. This is to the same decimal places as the `output` token.
     */
    function withdrawAndUnwrap(
        uint256 _amount,
        uint256 _minAmountOut,
        address _output,
        address _beneficiary,
        address _router,
        bool _isBassetOut
    ) external returns (uint256 outputQuantity);

    /**
     * @notice Claims only the tokens that have been immediately unlocked, not including
     * those that are in the lockers.
     */
    function claimReward() external;

    /**
     * @notice Claims all unlocked rewards for sender.
     * Note, this function is costly - the args for _claimRewards
     * should be determined off chain and then passed to other fn
     */
    function claimRewards() external;

    /**
     * @notice Claims all unlocked rewards for sender. Both immediately unlocked
     * rewards and also locked rewards past their time lock.
     * @param _first    Index of the first array element to claim
     * @param _last     Index of the last array element to claim
     */
    function claimRewards(uint256 _first, uint256 _last) external;

    /**
     * @notice Pokes a given account to reset the boost
     */
    function pokeBoost(address _account) external;

    /**
     * @notice Gets the last applicable timestamp for this reward period
     */
    function lastTimeRewardApplicable() external view returns (uint256);

    /**
     * @notice Calculates the amount of unclaimed rewards per token since last update,
     * and sums with stored to give the new cumulative reward per token
     * @return 'Reward' per staked token
     */
    function rewardPerToken() external view returns (uint256);

    /**
     * @notice Returned the units of IMMEDIATELY claimable rewards a user has to receive. Note - this
     * does NOT include the majority of rewards which will be locked up.
     * @param _account User address
     * @return Total reward amount earned
     */
    function earned(address _account) external view returns (uint256);

    /**
     * @notice Calculates all unclaimed reward data, finding both immediately unlocked rewards
     * and those that have passed their time lock.
     * @param _account User address
     * @return amount Total units of unclaimed rewards
     * @return first Index of the first userReward that has unlocked
     * @return last Index of the last userReward that has unlocked
     */
    function unclaimedRewards(address _account)
        external
        view
        returns (
            uint256 amount,
            uint256 first,
            uint256 last
        );
}

File 5 of 14 : IFeederPool.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.6;
pragma abicoder v2;

import "../masset/MassetStructs.sol";

abstract contract IFeederPool {
    // Mint
    function mint(
        address _input,
        uint256 _inputQuantity,
        uint256 _minOutputQuantity,
        address _recipient
    ) external virtual returns (uint256 mintOutput);

    function mintMulti(
        address[] calldata _inputs,
        uint256[] calldata _inputQuantities,
        uint256 _minOutputQuantity,
        address _recipient
    ) external virtual returns (uint256 mintOutput);

    function getMintOutput(address _input, uint256 _inputQuantity)
        external
        view
        virtual
        returns (uint256 mintOutput);

    function getMintMultiOutput(address[] calldata _inputs, uint256[] calldata _inputQuantities)
        external
        view
        virtual
        returns (uint256 mintOutput);

    // Swaps
    function swap(
        address _input,
        address _output,
        uint256 _inputQuantity,
        uint256 _minOutputQuantity,
        address _recipient
    ) external virtual returns (uint256 swapOutput);

    function getSwapOutput(
        address _input,
        address _output,
        uint256 _inputQuantity
    ) external view virtual returns (uint256 swapOutput);

    // Redemption
    function redeem(
        address _output,
        uint256 _fpTokenQuantity,
        uint256 _minOutputQuantity,
        address _recipient
    ) external virtual returns (uint256 outputQuantity);

    function redeemProportionately(
        uint256 _fpTokenQuantity,
        uint256[] calldata _minOutputQuantities,
        address _recipient
    ) external virtual returns (uint256[] memory outputQuantities);

    function redeemExactBassets(
        address[] calldata _outputs,
        uint256[] calldata _outputQuantities,
        uint256 _maxMassetQuantity,
        address _recipient
    ) external virtual returns (uint256 mAssetRedeemed);

    function getRedeemOutput(address _output, uint256 _fpTokenQuantity)
        external
        view
        virtual
        returns (uint256 bAssetOutput);

    function getRedeemExactBassetsOutput(
        address[] calldata _outputs,
        uint256[] calldata _outputQuantities
    ) external view virtual returns (uint256 mAssetAmount);

    // Views
    function mAsset() external view virtual returns (address);

    function getPrice() public view virtual returns (uint256 price, uint256 k);

    function getConfig() external view virtual returns (FeederConfig memory config);

    function getBasset(address _token)
        external
        view
        virtual
        returns (BassetPersonal memory personal, BassetData memory data);

    function getBassets()
        external
        view
        virtual
        returns (BassetPersonal[] memory personal, BassetData[] memory data);

    // SavingsManager
    function collectPlatformInterest()
        external
        virtual
        returns (uint256 mintAmount, uint256 newSupply);

    function collectPendingFees() external virtual;
}

File 6 of 14 : IMasset.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.6;
pragma abicoder v2;

import { BassetData, BassetPersonal } from "../masset/MassetStructs.sol";

abstract contract IMasset {
    // Mint
    function mint(
        address _input,
        uint256 _inputQuantity,
        uint256 _minOutputQuantity,
        address _recipient
    ) external virtual returns (uint256 mintOutput);

    function mintMulti(
        address[] calldata _inputs,
        uint256[] calldata _inputQuantities,
        uint256 _minOutputQuantity,
        address _recipient
    ) external virtual returns (uint256 mintOutput);

    function getMintOutput(address _input, uint256 _inputQuantity)
        external
        view
        virtual
        returns (uint256 mintOutput);

    function getMintMultiOutput(address[] calldata _inputs, uint256[] calldata _inputQuantities)
        external
        view
        virtual
        returns (uint256 mintOutput);

    // Swaps
    function swap(
        address _input,
        address _output,
        uint256 _inputQuantity,
        uint256 _minOutputQuantity,
        address _recipient
    ) external virtual returns (uint256 swapOutput);

    function getSwapOutput(
        address _input,
        address _output,
        uint256 _inputQuantity
    ) external view virtual returns (uint256 swapOutput);

    // Redemption
    function redeem(
        address _output,
        uint256 _mAssetQuantity,
        uint256 _minOutputQuantity,
        address _recipient
    ) external virtual returns (uint256 outputQuantity);

    function redeemMasset(
        uint256 _mAssetQuantity,
        uint256[] calldata _minOutputQuantities,
        address _recipient
    ) external virtual returns (uint256[] memory outputQuantities);

    function redeemExactBassets(
        address[] calldata _outputs,
        uint256[] calldata _outputQuantities,
        uint256 _maxMassetQuantity,
        address _recipient
    ) external virtual returns (uint256 mAssetRedeemed);

    function getRedeemOutput(address _output, uint256 _mAssetQuantity)
        external
        view
        virtual
        returns (uint256 bAssetOutput);

    function getRedeemExactBassetsOutput(
        address[] calldata _outputs,
        uint256[] calldata _outputQuantities
    ) external view virtual returns (uint256 mAssetAmount);

    // Views
    function getBasket() external view virtual returns (bool, bool);

    function getBasset(address _token)
        external
        view
        virtual
        returns (BassetPersonal memory personal, BassetData memory data);

    function getBassets()
        external
        view
        virtual
        returns (BassetPersonal[] memory personal, BassetData[] memory data);

    function bAssetIndexes(address) external view virtual returns (uint8);

    function getPrice() external view virtual returns (uint256 price, uint256 k);

    // SavingsManager
    function collectInterest() external virtual returns (uint256 swapFeesGained, uint256 newSupply);

    function collectPlatformInterest()
        external
        virtual
        returns (uint256 mintAmount, uint256 newSupply);

    // Admin
    function setCacheSize(uint256 _cacheSize) external virtual;

    function setFees(uint256 _swapFee, uint256 _redemptionFee) external virtual;

    function setTransferFeesFlag(address _bAsset, bool _flag) external virtual;

    function migrateBassets(address[] calldata _bAssets, address _newIntegration) external virtual;
}

File 7 of 14 : ISavingsContract.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.6;

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

interface ISavingsContractV1 {
    function depositInterest(uint256 _amount) external;

    function depositSavings(uint256 _amount) external returns (uint256 creditsIssued);

    function redeem(uint256 _amount) external returns (uint256 massetReturned);

    function exchangeRate() external view returns (uint256);

    function creditBalances(address) external view returns (uint256);
}

interface ISavingsContractV2 {
    // DEPRECATED but still backwards compatible
    function redeem(uint256 _amount) external returns (uint256 massetReturned);

    function creditBalances(address) external view returns (uint256); // V1 & V2 (use balanceOf)

    // --------------------------------------------

    function depositInterest(uint256 _amount) external; // V1 & V2

    function depositSavings(uint256 _amount) external returns (uint256 creditsIssued); // V1 & V2

    function depositSavings(uint256 _amount, address _beneficiary)
        external
        returns (uint256 creditsIssued); // V2

    function redeemCredits(uint256 _amount) external returns (uint256 underlyingReturned); // V2

    function redeemUnderlying(uint256 _amount) external returns (uint256 creditsBurned); // V2

    function exchangeRate() external view returns (uint256); // V1 & V2

    function balanceOfUnderlying(address _user) external view returns (uint256 underlying); // V2

    function underlyingToCredits(uint256 _underlying) external view returns (uint256 credits); // V2

    function creditsToUnderlying(uint256 _credits) external view returns (uint256 underlying); // V2

    function underlying() external view returns (IERC20 underlyingMasset); // V2
}

interface ISavingsContractV3 {
    // DEPRECATED but still backwards compatible
    function redeem(uint256 _amount) external returns (uint256 massetReturned);

    function creditBalances(address) external view returns (uint256); // V1 & V2 (use balanceOf)

    // --------------------------------------------

    function depositInterest(uint256 _amount) external; // V1 & V2

    function depositSavings(uint256 _amount) external returns (uint256 creditsIssued); // V1 & V2

    function depositSavings(uint256 _amount, address _beneficiary)
        external
        returns (uint256 creditsIssued); // V2

    function redeemCredits(uint256 _amount) external returns (uint256 underlyingReturned); // V2

    function redeemUnderlying(uint256 _amount) external returns (uint256 creditsBurned); // V2

    function exchangeRate() external view returns (uint256); // V1 & V2

    function balanceOfUnderlying(address _user) external view returns (uint256 underlying); // V2

    function underlyingToCredits(uint256 _underlying) external view returns (uint256 credits); // V2

    function creditsToUnderlying(uint256 _credits) external view returns (uint256 underlying); // V2

    function underlying() external view returns (IERC20 underlyingMasset); // V2

    // --------------------------------------------

    function redeemAndUnwrap(
        uint256 _amount,
        bool _isCreditAmt,
        uint256 _minAmountOut,
        address _output,
        address _beneficiary,
        address _router,
        bool _isBassetOut
    )
        external
        returns (
            uint256 creditsBurned,
            uint256 massetRedeemed,
            uint256 outputQuantity
        );

    function depositSavings(
        uint256 _underlying,
        address _beneficiary,
        address _referrer
    ) external returns (uint256 creditsIssued);
}

File 8 of 14 : IUniswapV2Router02.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.6;

interface IUniswapV2Router02 {
    function swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin, // calculated off chain
        address[] calldata path, // also worked out off chain
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapExactETHForTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable returns (uint256[] memory amounts);

    function getAmountsIn(uint256 amountOut, address[] calldata path)
        external
        view
        returns (uint256[] memory amounts);

    function getAmountsOut(uint256 amountIn, address[] calldata path)
        external
        view
        returns (uint256[] memory amounts);
}

File 9 of 14 : IBasicToken.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.6;

interface IBasicToken {
    function decimals() external view returns (uint8);
}

File 10 of 14 : ImmutableModule.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.6;

import { ModuleKeys } from "./ModuleKeys.sol";
import { INexus } from "../interfaces/INexus.sol";

/**
 * @title   ImmutableModule
 * @author  mStable
 * @dev     Subscribes to module updates from a given publisher and reads from its registry.
 *          Contract is used for upgradable proxy contracts.
 */
abstract contract ImmutableModule is ModuleKeys {
    INexus public immutable nexus;

    /**
     * @dev Initialization function for upgradable proxy contracts
     * @param _nexus Nexus contract address
     */
    constructor(address _nexus) {
        require(_nexus != address(0), "Nexus address is zero");
        nexus = INexus(_nexus);
    }

    /**
     * @dev Modifier to allow function calls only from the Governor.
     */
    modifier onlyGovernor() {
        _onlyGovernor();
        _;
    }

    function _onlyGovernor() internal view {
        require(msg.sender == _governor(), "Only governor can execute");
    }

    /**
     * @dev Modifier to allow function calls only from the Governor or the Keeper EOA.
     */
    modifier onlyKeeperOrGovernor() {
        _keeperOrGovernor();
        _;
    }

    function _keeperOrGovernor() internal view {
        require(msg.sender == _keeper() || msg.sender == _governor(), "Only keeper or governor");
    }

    /**
     * @dev Modifier to allow function calls only from the Governance.
     *      Governance is either Governor address or Governance address.
     */
    modifier onlyGovernance() {
        require(
            msg.sender == _governor() || msg.sender == _governance(),
            "Only governance can execute"
        );
        _;
    }

    /**
     * @dev Returns Governor address from the Nexus
     * @return Address of Governor Contract
     */
    function _governor() internal view returns (address) {
        return nexus.governor();
    }

    /**
     * @dev Returns Governance Module address from the Nexus
     * @return Address of the Governance (Phase 2)
     */
    function _governance() internal view returns (address) {
        return nexus.getModule(KEY_GOVERNANCE);
    }

    /**
     * @dev Return Keeper address from the Nexus.
     *      This account is used for operational transactions that
     *      don't need multiple signatures.
     * @return  Address of the Keeper externally owned account.
     */
    function _keeper() internal view returns (address) {
        return nexus.getModule(KEY_KEEPER);
    }

    /**
     * @dev Return SavingsManager Module address from the Nexus
     * @return Address of the SavingsManager Module contract
     */
    function _savingsManager() internal view returns (address) {
        return nexus.getModule(KEY_SAVINGS_MANAGER);
    }

    /**
     * @dev Return Recollateraliser Module address from the Nexus
     * @return  Address of the Recollateraliser Module contract (Phase 2)
     */
    function _recollateraliser() internal view returns (address) {
        return nexus.getModule(KEY_RECOLLATERALISER);
    }

    /**
     * @dev Return Liquidator Module address from the Nexus
     * @return  Address of the Liquidator Module contract
     */
    function _liquidator() internal view returns (address) {
        return nexus.getModule(KEY_LIQUIDATOR);
    }

    /**
     * @dev Return ProxyAdmin Module address from the Nexus
     * @return Address of the ProxyAdmin Module contract
     */
    function _proxyAdmin() internal view returns (address) {
        return nexus.getModule(KEY_PROXY_ADMIN);
    }
}

File 11 of 14 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

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

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

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

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 12 of 14 : MassetStructs.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.6;

struct BassetPersonal {
    // Address of the bAsset
    address addr;
    // Address of the bAsset
    address integrator;
    // An ERC20 can charge transfer fee, for example USDT, DGX tokens.
    bool hasTxFee; // takes a byte in storage
    // Status of the bAsset
    BassetStatus status;
}

struct BassetData {
    // 1 Basset * ratio / ratioScale == x Masset (relative value)
    // If ratio == 10e8 then 1 bAsset = 10 mAssets
    // A ratio is divised as 10^(18-tokenDecimals) * measurementMultiple(relative value of 1 base unit)
    uint128 ratio;
    // Amount of the Basset that is held in Collateral
    uint128 vaultBalance;
}

// Status of the Basset - has it broken its peg?
enum BassetStatus {
    Default,
    Normal,
    BrokenBelowPeg,
    BrokenAbovePeg,
    Blacklisted,
    Liquidating,
    Liquidated,
    Failed
}

struct BasketState {
    bool undergoingRecol;
    bool failed;
}

struct FeederConfig {
    uint256 supply;
    uint256 a;
    WeightLimits limits;
}

struct InvariantConfig {
    uint256 supply;
    uint256 a;
    WeightLimits limits;
    uint256 recolFee;
}

struct BasicConfig {
    uint256 a;
    WeightLimits limits;
}

struct WeightLimits {
    uint128 min;
    uint128 max;
}

struct AmpData {
    uint64 initialA;
    uint64 targetA;
    uint64 rampStartTime;
    uint64 rampEndTime;
}

struct FeederData {
    uint256 swapFee;
    uint256 redemptionFee;
    uint256 govFee;
    uint256 pendingFees;
    uint256 cacheSize;
    BassetPersonal[] bAssetPersonal;
    BassetData[] bAssetData;
    AmpData ampData;
    WeightLimits weightLimits;
}

struct MassetData {
    uint256 swapFee;
    uint256 redemptionFee;
    uint256 cacheSize;
    uint256 surplus;
    BassetPersonal[] bAssetPersonal;
    BassetData[] bAssetData;
    BasketState basket;
    AmpData ampData;
    WeightLimits weightLimits;
}

struct AssetData {
    uint8 idx;
    uint256 amt;
    BassetPersonal personal;
}

struct Asset {
    uint8 idx;
    address addr;
    bool exists;
}

File 13 of 14 : ModuleKeys.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.6;

/**
 * @title  ModuleKeys
 * @author mStable
 * @notice Provides system wide access to the byte32 represntations of system modules
 *         This allows each system module to be able to reference and update one another in a
 *         friendly way
 * @dev    keccak256() values are hardcoded to avoid re-evaluation of the constants at runtime.
 */
contract ModuleKeys {
    // Governance
    // ===========
    // keccak256("Governance");
    bytes32 internal constant KEY_GOVERNANCE =
        0x9409903de1e6fd852dfc61c9dacb48196c48535b60e25abf92acc92dd689078d;
    //keccak256("Staking");
    bytes32 internal constant KEY_STAKING =
        0x1df41cd916959d1163dc8f0671a666ea8a3e434c13e40faef527133b5d167034;
    //keccak256("ProxyAdmin");
    bytes32 internal constant KEY_PROXY_ADMIN =
        0x96ed0203eb7e975a4cbcaa23951943fa35c5d8288117d50c12b3d48b0fab48d1;

    // mStable
    // =======
    // keccak256("OracleHub");
    bytes32 internal constant KEY_ORACLE_HUB =
        0x8ae3a082c61a7379e2280f3356a5131507d9829d222d853bfa7c9fe1200dd040;
    // keccak256("Manager");
    bytes32 internal constant KEY_MANAGER =
        0x6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f;
    //keccak256("Recollateraliser");
    bytes32 internal constant KEY_RECOLLATERALISER =
        0x39e3ed1fc335ce346a8cbe3e64dd525cf22b37f1e2104a755e761c3c1eb4734f;
    //keccak256("MetaToken");
    bytes32 internal constant KEY_META_TOKEN =
        0xea7469b14936af748ee93c53b2fe510b9928edbdccac3963321efca7eb1a57a2;
    // keccak256("SavingsManager");
    bytes32 internal constant KEY_SAVINGS_MANAGER =
        0x12fe936c77a1e196473c4314f3bed8eeac1d757b319abb85bdda70df35511bf1;
    // keccak256("Liquidator");
    bytes32 internal constant KEY_LIQUIDATOR =
        0x1e9cb14d7560734a61fa5ff9273953e971ff3cd9283c03d8346e3264617933d4;
    // keccak256("InterestValidator");
    bytes32 internal constant KEY_INTEREST_VALIDATOR =
        0xc10a28f028c7f7282a03c90608e38a4a646e136e614e4b07d119280c5f7f839f;
    // keccak256("Keeper");
    bytes32 internal constant KEY_KEEPER =
        0x4f78afe9dfc9a0cb0441c27b9405070cd2a48b490636a7bdd09f355e33a5d7de;
}

File 14 of 14 : INexus.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.6;

/**
 * @title INexus
 * @dev Basic interface for interacting with the Nexus i.e. SystemKernel
 */
interface INexus {
    function governor() external view returns (address);

    function getModule(bytes32 key) external view returns (address);

    function proposeModule(bytes32 _key, address _addr) external;

    function cancelProposedModule(bytes32 _key) external;

    function acceptProposedModule(bytes32 _key) external;

    function acceptProposedModules(bytes32[] calldata _keys) external;

    function requestLockModule(bytes32 _key) external;

    function cancelLockModule(bytes32 _key) external;

    function lockModule(bytes32 _key) external;
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_nexus","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"address","name":"_spender","type":"address"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_mAsset","type":"address"},{"internalType":"address[]","name":"_bAssets","type":"address[]"},{"internalType":"address[]","name":"_fPools","type":"address[]"},{"internalType":"address[]","name":"_fAssets","type":"address[]"},{"internalType":"address","name":"_save","type":"address"},{"internalType":"address","name":"_vault","type":"address"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_mAsset","type":"address"},{"internalType":"address","name":"_uniswap","type":"address"},{"internalType":"uint256","name":"_ethAmount","type":"uint256"},{"internalType":"address[]","name":"_path","type":"address[]"}],"name":"estimate_saveViaUniswapETH","outputs":[{"internalType":"uint256","name":"out","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nexus","outputs":[{"internalType":"contract INexus","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_mAsset","type":"address"},{"internalType":"address","name":"_save","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"saveAndStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_mAsset","type":"address"},{"internalType":"address","name":"_save","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"saveAndStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_mAsset","type":"address"},{"internalType":"address","name":"_save","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_bAsset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minOut","type":"uint256"},{"internalType":"bool","name":"_stake","type":"bool"}],"name":"saveViaMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_mAsset","type":"address"},{"internalType":"address","name":"_save","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_bAsset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minOut","type":"uint256"},{"internalType":"bool","name":"_stake","type":"bool"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"saveViaMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_mAsset","type":"address"},{"internalType":"address","name":"_save","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_feeder","type":"address"},{"internalType":"address","name":"_fAsset","type":"address"},{"internalType":"uint256","name":"_fAssetQuantity","type":"uint256"},{"internalType":"uint256","name":"_minOutputQuantity","type":"uint256"},{"internalType":"bool","name":"_stake","type":"bool"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"saveViaSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_mAsset","type":"address"},{"internalType":"address","name":"_save","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_feeder","type":"address"},{"internalType":"address","name":"_fAsset","type":"address"},{"internalType":"uint256","name":"_fAssetQuantity","type":"uint256"},{"internalType":"uint256","name":"_minOutputQuantity","type":"uint256"},{"internalType":"bool","name":"_stake","type":"bool"}],"name":"saveViaSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_mAsset","type":"address"},{"internalType":"address","name":"_save","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_uniswap","type":"address"},{"internalType":"uint256","name":"_amountOutMin","type":"uint256"},{"internalType":"address[]","name":"_path","type":"address[]"},{"internalType":"uint256","name":"_minOutMStable","type":"uint256"},{"internalType":"bool","name":"_stake","type":"bool"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"saveViaUniswapETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_mAsset","type":"address"},{"internalType":"address","name":"_save","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_uniswap","type":"address"},{"internalType":"uint256","name":"_amountOutMin","type":"uint256"},{"internalType":"address[]","name":"_path","type":"address[]"},{"internalType":"uint256","name":"_minOutMStable","type":"uint256"},{"internalType":"bool","name":"_stake","type":"bool"}],"name":"saveViaUniswapETH","outputs":[],"stateMutability":"payable","type":"function"}]

60a06040523480156200001157600080fd5b50604051620021d5380380620021d58339810160408190526200003491620000a7565b806001600160a01b038116620000905760405162461bcd60e51b815260206004820152601560248201527f4e657875732061646472657373206973207a65726f0000000000000000000000604482015260640160405180910390fd5b60601b6001600160601b03191660805250620000d9565b600060208284031215620000ba57600080fd5b81516001600160a01b0381168114620000d257600080fd5b9392505050565b60805160601c6120cf62000106600039600081816101c10152818161123e01526112c901526120cf6000f3fe6080604052600436106100c25760003560e01c80638b4df6741161007f578063b132fdc211610059578063b132fdc214610200578063b566409e14610220578063b6623e4c14610240578063fa635f2b1461026e57600080fd5b80638b4df6741461016f5780639491416e1461018f578063a3f5c1d2146101af57600080fd5b806328f847f4146100c757806338111242146100dc5780635011fe4e146100fc57806364202c9f1461010f57806372a9f0421461012f5780637e5465ba1461014f575b600080fd5b6100da6100d5366004611922565b61028e565b005b3480156100e857600080fd5b506100da6100f73660046119eb565b6102ac565b6100da61010a36600461187e565b6102c6565b34801561011b57600080fd5b506100da61012a366004611ce2565b6102e4565b34801561013b57600080fd5b506100da61014a366004611af5565b6102fc565b34801561015b57600080fd5b506100da61016a366004611704565b610312565b34801561017b57600080fd5b506100da61018a366004611a6f565b610328565b34801561019b57600080fd5b506100da6101aa366004611b46565b610342565b3480156101bb57600080fd5b506101e37f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561020c57600080fd5b506100da61021b366004611c21565b610358565b34801561022c57600080fd5b506100da61023b3660046117d4565b610446565b34801561024c57600080fd5b5061026061025b366004611bae565b610457565b6040519081526020016101f7565b34801561027a57600080fd5b506100da61028936600461173d565b6105d2565b6102a08a8a8a8a8a8a8a8a8a8a6105e4565b50505050505050505050565b6102bd87878787878787600061084c565b50505050505050565b6102d989898989898989898960006105e4565b505050505050505050565b6102ec6109bc565b6102f7838383610a49565b505050565b61030c8484848460016000610b5c565b50505050565b61031a6109bc565b6103248282610bf8565b5050565b610338888888888888888861084c565b5050505050505050565b61035185858585600186610b5c565b5050505050565b6103606109bc565b61036a8983610bf8565b6103748282610bf8565b61037f88888b610a49565b8483146103d35760405162461bcd60e51b815260206004820152601a60248201527f4d69736d61746368696e672066506f6f6c732f6641737365747300000000000060448201526064015b60405180910390fd5b60005b858110156102a0576104348585838181106103f3576103f3612047565b905060200201602081019061040891906116ca565b88888481811061041a5761041a612047565b905060200201602081019061042f91906116ca565b610bf8565b8061043e81612016565b9150506103d6565b6102d9898989898989898989610c9c565b60006001600160a01b03861661047f5760405162461bcd60e51b81526004016103ca90611ed0565b6001600160a01b0385166104c75760405162461bcd60e51b815260206004820152600f60248201526e0496e76616c696420756e697377617608c1b60448201526064016103ca565b60006105078686868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610e5a92505050565b90506001600160a01b03871663119849cf8585610525600182611fd3565b81811061053457610534612047565b905060200201602081019061054991906116ca565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526024810184905260440160206040518083038186803b15801561058f57600080fd5b505afa1580156105a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c79190611e1b565b979650505050505050565b61033888888888888888886000610c9c565b6001600160a01b038a1661060a5760405162461bcd60e51b81526004016103ca90611ed0565b6001600160a01b0389166106305760405162461bcd60e51b81526004016103ca90611eaa565b6001600160a01b0388166106565760405162461bcd60e51b81526004016103ca90611e83565b6001600160a01b03871661069e5760405162461bcd60e51b815260206004820152600f60248201526e0496e76616c696420756e697377617608c1b60448201526064016103ca565b60006001600160a01b038816637ff36ab534898989306106c0426103e8611fbb565b6040518763ffffffff1660e01b81526004016106e0959493929190611ef8565b6000604051808303818588803b1580156106f957600080fd5b505af115801561070d573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526107369190810190611d39565b905060006001600160a01b038c1663f74bfe8e8888610756600182611fd3565b81811061076557610765612047565b905060200201602081019061077a91906116ca565b84600186516107899190611fd3565b8151811061079957610799612047565b60209081029190910101516040516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482015260448101889052306064820152608401602060405180830381600087803b1580156107f757600080fd5b505af115801561080b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082f9190611e1b565b905061083e8b8b838787610f13565b505050505050505050505050565b6001600160a01b0388166108725760405162461bcd60e51b81526004016103ca90611ed0565b6001600160a01b0387166108985760405162461bcd60e51b81526004016103ca90611eaa565b6001600160a01b0386166108be5760405162461bcd60e51b81526004016103ca90611e83565b6001600160a01b0385166109055760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a590818905cdcd95d60921b60448201526064016103ca565b61091a6001600160a01b03861633308761119b565b604051637ba5ff4760e11b81526001600160a01b0386811660048301526024820186905260448201859052306064830152600091908a169063f74bfe8e90608401602060405180830381600087803b15801561097557600080fd5b505af1158015610989573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ad9190611e1b565b90506102d98888838686610f13565b6109c4611206565b6001600160a01b0316336001600160a01b031614806109fb57506109e66112c5565b6001600160a01b0316336001600160a01b0316145b610a475760405162461bcd60e51b815260206004820152601760248201527f4f6e6c79206b6565706572206f7220676f7665726e6f7200000000000000000060448201526064016103ca565b565b6001600160a01b038116610a915760405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b21039b832b73232b960891b60448201526064016103ca565b60005b8281101561030c576000848483818110610ab057610ab0612047565b9050602002016020810190610ac591906116ca565b6001600160a01b03161415610b0c5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b60448201526064016103ca565b610b4a82600019868685818110610b2557610b25612047565b9050602002016020810190610b3a91906116ca565b6001600160a01b03169190611320565b80610b5481612016565b915050610a94565b6001600160a01b038616610b825760405162461bcd60e51b81526004016103ca90611ed0565b6001600160a01b038516610ba85760405162461bcd60e51b81526004016103ca90611eaa565b6001600160a01b038416610bce5760405162461bcd60e51b81526004016103ca90611e83565b610be36001600160a01b03871633308661119b565b610bf08585858585610f13565b505050505050565b6001600160a01b038116610c405760405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b21039b832b73232b960891b60448201526064016103ca565b6001600160a01b038216610c865760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b60448201526064016103ca565b6103246001600160a01b03831682600019611320565b6001600160a01b038616610ce35760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b2103332b2b232b960911b60448201526064016103ca565b6001600160a01b038916610d095760405162461bcd60e51b81526004016103ca90611ed0565b6001600160a01b038816610d2f5760405162461bcd60e51b81526004016103ca90611eaa565b6001600160a01b038716610d555760405162461bcd60e51b81526004016103ca90611e83565b6001600160a01b038516610d9b5760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a59081a5b9c1d5d609a1b60448201526064016103ca565b610db06001600160a01b03861633308761119b565b60405163d5bcb9b560e01b81526001600160a01b0386811660048301528a8116602483015260448201869052606482018590523060848301526000919088169063d5bcb9b59060a401602060405180830381600087803b158015610e1357600080fd5b505af1158015610e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4b9190611e1b565b90506102a08989838686610f13565b600080846001600160a01b031663d06ca61f85856040518363ffffffff1660e01b8152600401610e8b929190611f64565b60006040518083038186803b158015610ea357600080fd5b505afa158015610eb7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610edf9190810190611d39565b90508060018251610ef09190611fd3565b81518110610f0057610f00612047565b60200260200101519150505b9392505050565b818015610f2857506001600160a01b03811615155b1561102357604051630ee7e5a360e11b8152600481018490523060248201526001600160a01b03828116604483015260009190871690631dcfcb46906064015b602060405180830381600087803b158015610f8257600080fd5b505af1158015610f96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fba9190611e1b565b6040516356e4bb9760e11b8152336004820152602481018290529091506001600160a01b0386169063adc9772e90604401600060405180830381600087803b15801561100557600080fd5b505af1158015611019573d6000803e3d6000fd5b5050505050610351565b81801561103757506001600160a01b038116155b156110725760405163590745c560e01b8152600481018490523060248201526000906001600160a01b0387169063590745c590604401610f68565b8115801561108857506001600160a01b03811615155b1561111b57604051630ee7e5a360e11b8152600481018490523360248201526001600160a01b038281166044830152861690631dcfcb4690606401602060405180830381600087803b1580156110dd57600080fd5b505af11580156110f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111159190611e1b565b50610351565b60405163590745c560e01b8152600481018490523360248201526001600160a01b0386169063590745c590604401602060405180830381600087803b15801561116357600080fd5b505af1158015611177573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf09190611e1b565b6040516001600160a01b038085166024830152831660448201526064810182905261030c9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611444565b6040516385acd64160e01b81527f4f78afe9dfc9a0cb0441c27b9405070cd2a48b490636a7bdd09f355e33a5d7de60048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906385acd6419060240160206040518083038186803b15801561128857600080fd5b505afa15801561129c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c091906116e7565b905090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b15801561128857600080fd5b8015806113a95750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b15801561136f57600080fd5b505afa158015611383573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a79190611e1b565b155b6114145760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60648201526084016103ca565b6040516001600160a01b0383166024820152604481018290526102f790849063095ea7b360e01b906064016111cf565b6000611499826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166115169092919063ffffffff16565b8051909150156102f757808060200190518101906114b79190611dfe565b6102f75760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016103ca565b6060611525848460008561152d565b949350505050565b60608247101561158e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016103ca565b843b6115dc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103ca565b600080866001600160a01b031685876040516115f89190611e34565b60006040518083038185875af1925050503d8060008114611635576040519150601f19603f3d011682016040523d82523d6000602084013e61163a565b606091505b50915091506105c782828660608315611654575081610f0c565b8251156116645782518084602001fd5b8160405162461bcd60e51b81526004016103ca9190611e50565b60008083601f84011261169057600080fd5b50813567ffffffffffffffff8111156116a857600080fd5b6020830191508360208260051b85010111156116c357600080fd5b9250929050565b6000602082840312156116dc57600080fd5b8135610f0c81612073565b6000602082840312156116f957600080fd5b8151610f0c81612073565b6000806040838503121561171757600080fd5b823561172281612073565b9150602083013561173281612073565b809150509250929050565b600080600080600080600080610100898b03121561175a57600080fd5b883561176581612073565b9750602089013561177581612073565b9650604089013561178581612073565b9550606089013561179581612073565b945060808901356117a581612073565b935060a0890135925060c0890135915060e08901356117c38161208b565b809150509295985092959890939650565b60008060008060008060008060006101208a8c0312156117f357600080fd5b89356117fe81612073565b985060208a013561180e81612073565b975060408a013561181e81612073565b965060608a013561182e81612073565b955060808a013561183e81612073565b945060a08a0135935060c08a0135925060e08a013561185c8161208b565b91506101008a013561186d81612073565b809150509295985092959850929598565b60008060008060008060008060006101008a8c03121561189d57600080fd5b89356118a881612073565b985060208a01356118b881612073565b975060408a01356118c881612073565b965060608a01356118d881612073565b955060808a0135945060a08a013567ffffffffffffffff8111156118fb57600080fd5b6119078c828d0161167e565b90955093505060c08a0135915060e08a013561186d8161208b565b6000806000806000806000806000806101208b8d03121561194257600080fd5b8a3561194d81612073565b995060208b013561195d81612073565b985060408b013561196d81612073565b975060608b013561197d81612073565b965060808b0135955060a08b013567ffffffffffffffff8111156119a057600080fd5b6119ac8d828e0161167e565b90965094505060c08b0135925060e08b01356119c78161208b565b91506101008b01356119d881612073565b809150509295989b9194979a5092959850565b600080600080600080600060e0888a031215611a0657600080fd5b8735611a1181612073565b96506020880135611a2181612073565b95506040880135611a3181612073565b94506060880135611a4181612073565b93506080880135925060a0880135915060c0880135611a5f8161208b565b8091505092959891949750929550565b600080600080600080600080610100898b031215611a8c57600080fd5b8835611a9781612073565b97506020890135611aa781612073565b96506040890135611ab781612073565b95506060890135611ac781612073565b94506080890135935060a0890135925060c0890135611ae58161208b565b915060e08901356117c381612073565b60008060008060808587031215611b0b57600080fd5b8435611b1681612073565b93506020850135611b2681612073565b92506040850135611b3681612073565b9396929550929360600135925050565b600080600080600060a08688031215611b5e57600080fd5b8535611b6981612073565b94506020860135611b7981612073565b93506040860135611b8981612073565b9250606086013591506080860135611ba081612073565b809150509295509295909350565b600080600080600060808688031215611bc657600080fd5b8535611bd181612073565b94506020860135611be181612073565b935060408601359250606086013567ffffffffffffffff811115611c0457600080fd5b611c108882890161167e565b969995985093965092949392505050565b600080600080600080600080600060c08a8c031215611c3f57600080fd5b8935611c4a81612073565b985060208a013567ffffffffffffffff80821115611c6757600080fd5b611c738d838e0161167e565b909a50985060408c0135915080821115611c8c57600080fd5b611c988d838e0161167e565b909850965060608c0135915080821115611cb157600080fd5b50611cbe8c828d0161167e565b90955093505060808a0135611cd281612073565b915060a08a013561186d81612073565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a8682870161167e565b9094509250506020840135611d2e81612073565b809150509250925092565b60006020808385031215611d4c57600080fd5b825167ffffffffffffffff80821115611d6457600080fd5b818501915085601f830112611d7857600080fd5b815181811115611d8a57611d8a61205d565b8060051b604051601f19603f83011681018181108582111715611daf57611daf61205d565b604052828152858101935084860182860187018a1015611dce57600080fd5b600095505b83861015611df1578051855260019590950194938601938601611dd3565b5098975050505050505050565b600060208284031215611e1057600080fd5b8151610f0c8161208b565b600060208284031215611e2d57600080fd5b5051919050565b60008251611e46818460208701611fea565b9190910192915050565b6020815260008251806020840152611e6f816040850160208701611fea565b601f01601f19169190910160400192915050565b6020808252600d908201526c125b9d985b1a59081d985d5b1d609a1b604082015260600190565b6020808252600c908201526b496e76616c6964207361766560a01b604082015260600190565b6020808252600e908201526d125b9d985b1a59081b505cdcd95d60921b604082015260600190565b85815260806020808301829052908201859052600090869060a08401835b88811015611f44578335611f2981612073565b6001600160a01b031682529282019290820190600101611f16565b506001600160a01b03969096166040850152505050606001529392505050565b6000604082018483526020604081850152818551808452606086019150828701935060005b81811015611fae5784516001600160a01b031683529383019391830191600101611f89565b5090979650505050505050565b60008219821115611fce57611fce612031565b500190565b600082821015611fe557611fe5612031565b500390565b60005b83811015612005578181015183820152602001611fed565b8381111561030c5750506000910152565b600060001982141561202a5761202a612031565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461208857600080fd5b50565b801515811461208857600080fdfea2646970667358221220f4bd9ed4bb7fa03581f0613378a49a1f8b9727170880e2e4575e1c249b54c9ad64736f6c63430008060033000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3

Deployed Bytecode

0x6080604052600436106100c25760003560e01c80638b4df6741161007f578063b132fdc211610059578063b132fdc214610200578063b566409e14610220578063b6623e4c14610240578063fa635f2b1461026e57600080fd5b80638b4df6741461016f5780639491416e1461018f578063a3f5c1d2146101af57600080fd5b806328f847f4146100c757806338111242146100dc5780635011fe4e146100fc57806364202c9f1461010f57806372a9f0421461012f5780637e5465ba1461014f575b600080fd5b6100da6100d5366004611922565b61028e565b005b3480156100e857600080fd5b506100da6100f73660046119eb565b6102ac565b6100da61010a36600461187e565b6102c6565b34801561011b57600080fd5b506100da61012a366004611ce2565b6102e4565b34801561013b57600080fd5b506100da61014a366004611af5565b6102fc565b34801561015b57600080fd5b506100da61016a366004611704565b610312565b34801561017b57600080fd5b506100da61018a366004611a6f565b610328565b34801561019b57600080fd5b506100da6101aa366004611b46565b610342565b3480156101bb57600080fd5b506101e37f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb381565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561020c57600080fd5b506100da61021b366004611c21565b610358565b34801561022c57600080fd5b506100da61023b3660046117d4565b610446565b34801561024c57600080fd5b5061026061025b366004611bae565b610457565b6040519081526020016101f7565b34801561027a57600080fd5b506100da61028936600461173d565b6105d2565b6102a08a8a8a8a8a8a8a8a8a8a6105e4565b50505050505050505050565b6102bd87878787878787600061084c565b50505050505050565b6102d989898989898989898960006105e4565b505050505050505050565b6102ec6109bc565b6102f7838383610a49565b505050565b61030c8484848460016000610b5c565b50505050565b61031a6109bc565b6103248282610bf8565b5050565b610338888888888888888861084c565b5050505050505050565b61035185858585600186610b5c565b5050505050565b6103606109bc565b61036a8983610bf8565b6103748282610bf8565b61037f88888b610a49565b8483146103d35760405162461bcd60e51b815260206004820152601a60248201527f4d69736d61746368696e672066506f6f6c732f6641737365747300000000000060448201526064015b60405180910390fd5b60005b858110156102a0576104348585838181106103f3576103f3612047565b905060200201602081019061040891906116ca565b88888481811061041a5761041a612047565b905060200201602081019061042f91906116ca565b610bf8565b8061043e81612016565b9150506103d6565b6102d9898989898989898989610c9c565b60006001600160a01b03861661047f5760405162461bcd60e51b81526004016103ca90611ed0565b6001600160a01b0385166104c75760405162461bcd60e51b815260206004820152600f60248201526e0496e76616c696420756e697377617608c1b60448201526064016103ca565b60006105078686868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610e5a92505050565b90506001600160a01b03871663119849cf8585610525600182611fd3565b81811061053457610534612047565b905060200201602081019061054991906116ca565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526024810184905260440160206040518083038186803b15801561058f57600080fd5b505afa1580156105a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c79190611e1b565b979650505050505050565b61033888888888888888886000610c9c565b6001600160a01b038a1661060a5760405162461bcd60e51b81526004016103ca90611ed0565b6001600160a01b0389166106305760405162461bcd60e51b81526004016103ca90611eaa565b6001600160a01b0388166106565760405162461bcd60e51b81526004016103ca90611e83565b6001600160a01b03871661069e5760405162461bcd60e51b815260206004820152600f60248201526e0496e76616c696420756e697377617608c1b60448201526064016103ca565b60006001600160a01b038816637ff36ab534898989306106c0426103e8611fbb565b6040518763ffffffff1660e01b81526004016106e0959493929190611ef8565b6000604051808303818588803b1580156106f957600080fd5b505af115801561070d573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526107369190810190611d39565b905060006001600160a01b038c1663f74bfe8e8888610756600182611fd3565b81811061076557610765612047565b905060200201602081019061077a91906116ca565b84600186516107899190611fd3565b8151811061079957610799612047565b60209081029190910101516040516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482015260448101889052306064820152608401602060405180830381600087803b1580156107f757600080fd5b505af115801561080b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082f9190611e1b565b905061083e8b8b838787610f13565b505050505050505050505050565b6001600160a01b0388166108725760405162461bcd60e51b81526004016103ca90611ed0565b6001600160a01b0387166108985760405162461bcd60e51b81526004016103ca90611eaa565b6001600160a01b0386166108be5760405162461bcd60e51b81526004016103ca90611e83565b6001600160a01b0385166109055760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a590818905cdcd95d60921b60448201526064016103ca565b61091a6001600160a01b03861633308761119b565b604051637ba5ff4760e11b81526001600160a01b0386811660048301526024820186905260448201859052306064830152600091908a169063f74bfe8e90608401602060405180830381600087803b15801561097557600080fd5b505af1158015610989573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ad9190611e1b565b90506102d98888838686610f13565b6109c4611206565b6001600160a01b0316336001600160a01b031614806109fb57506109e66112c5565b6001600160a01b0316336001600160a01b0316145b610a475760405162461bcd60e51b815260206004820152601760248201527f4f6e6c79206b6565706572206f7220676f7665726e6f7200000000000000000060448201526064016103ca565b565b6001600160a01b038116610a915760405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b21039b832b73232b960891b60448201526064016103ca565b60005b8281101561030c576000848483818110610ab057610ab0612047565b9050602002016020810190610ac591906116ca565b6001600160a01b03161415610b0c5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b60448201526064016103ca565b610b4a82600019868685818110610b2557610b25612047565b9050602002016020810190610b3a91906116ca565b6001600160a01b03169190611320565b80610b5481612016565b915050610a94565b6001600160a01b038616610b825760405162461bcd60e51b81526004016103ca90611ed0565b6001600160a01b038516610ba85760405162461bcd60e51b81526004016103ca90611eaa565b6001600160a01b038416610bce5760405162461bcd60e51b81526004016103ca90611e83565b610be36001600160a01b03871633308661119b565b610bf08585858585610f13565b505050505050565b6001600160a01b038116610c405760405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b21039b832b73232b960891b60448201526064016103ca565b6001600160a01b038216610c865760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b60448201526064016103ca565b6103246001600160a01b03831682600019611320565b6001600160a01b038616610ce35760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b2103332b2b232b960911b60448201526064016103ca565b6001600160a01b038916610d095760405162461bcd60e51b81526004016103ca90611ed0565b6001600160a01b038816610d2f5760405162461bcd60e51b81526004016103ca90611eaa565b6001600160a01b038716610d555760405162461bcd60e51b81526004016103ca90611e83565b6001600160a01b038516610d9b5760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a59081a5b9c1d5d609a1b60448201526064016103ca565b610db06001600160a01b03861633308761119b565b60405163d5bcb9b560e01b81526001600160a01b0386811660048301528a8116602483015260448201869052606482018590523060848301526000919088169063d5bcb9b59060a401602060405180830381600087803b158015610e1357600080fd5b505af1158015610e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4b9190611e1b565b90506102a08989838686610f13565b600080846001600160a01b031663d06ca61f85856040518363ffffffff1660e01b8152600401610e8b929190611f64565b60006040518083038186803b158015610ea357600080fd5b505afa158015610eb7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610edf9190810190611d39565b90508060018251610ef09190611fd3565b81518110610f0057610f00612047565b60200260200101519150505b9392505050565b818015610f2857506001600160a01b03811615155b1561102357604051630ee7e5a360e11b8152600481018490523060248201526001600160a01b03828116604483015260009190871690631dcfcb46906064015b602060405180830381600087803b158015610f8257600080fd5b505af1158015610f96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fba9190611e1b565b6040516356e4bb9760e11b8152336004820152602481018290529091506001600160a01b0386169063adc9772e90604401600060405180830381600087803b15801561100557600080fd5b505af1158015611019573d6000803e3d6000fd5b5050505050610351565b81801561103757506001600160a01b038116155b156110725760405163590745c560e01b8152600481018490523060248201526000906001600160a01b0387169063590745c590604401610f68565b8115801561108857506001600160a01b03811615155b1561111b57604051630ee7e5a360e11b8152600481018490523360248201526001600160a01b038281166044830152861690631dcfcb4690606401602060405180830381600087803b1580156110dd57600080fd5b505af11580156110f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111159190611e1b565b50610351565b60405163590745c560e01b8152600481018490523360248201526001600160a01b0386169063590745c590604401602060405180830381600087803b15801561116357600080fd5b505af1158015611177573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf09190611e1b565b6040516001600160a01b038085166024830152831660448201526064810182905261030c9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611444565b6040516385acd64160e01b81527f4f78afe9dfc9a0cb0441c27b9405070cd2a48b490636a7bdd09f355e33a5d7de60048201526000907f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb36001600160a01b0316906385acd6419060240160206040518083038186803b15801561128857600080fd5b505afa15801561129c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c091906116e7565b905090565b60007f000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb36001600160a01b0316630c340a246040518163ffffffff1660e01b815260040160206040518083038186803b15801561128857600080fd5b8015806113a95750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b15801561136f57600080fd5b505afa158015611383573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a79190611e1b565b155b6114145760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b60648201526084016103ca565b6040516001600160a01b0383166024820152604481018290526102f790849063095ea7b360e01b906064016111cf565b6000611499826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166115169092919063ffffffff16565b8051909150156102f757808060200190518101906114b79190611dfe565b6102f75760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016103ca565b6060611525848460008561152d565b949350505050565b60608247101561158e5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016103ca565b843b6115dc5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103ca565b600080866001600160a01b031685876040516115f89190611e34565b60006040518083038185875af1925050503d8060008114611635576040519150601f19603f3d011682016040523d82523d6000602084013e61163a565b606091505b50915091506105c782828660608315611654575081610f0c565b8251156116645782518084602001fd5b8160405162461bcd60e51b81526004016103ca9190611e50565b60008083601f84011261169057600080fd5b50813567ffffffffffffffff8111156116a857600080fd5b6020830191508360208260051b85010111156116c357600080fd5b9250929050565b6000602082840312156116dc57600080fd5b8135610f0c81612073565b6000602082840312156116f957600080fd5b8151610f0c81612073565b6000806040838503121561171757600080fd5b823561172281612073565b9150602083013561173281612073565b809150509250929050565b600080600080600080600080610100898b03121561175a57600080fd5b883561176581612073565b9750602089013561177581612073565b9650604089013561178581612073565b9550606089013561179581612073565b945060808901356117a581612073565b935060a0890135925060c0890135915060e08901356117c38161208b565b809150509295985092959890939650565b60008060008060008060008060006101208a8c0312156117f357600080fd5b89356117fe81612073565b985060208a013561180e81612073565b975060408a013561181e81612073565b965060608a013561182e81612073565b955060808a013561183e81612073565b945060a08a0135935060c08a0135925060e08a013561185c8161208b565b91506101008a013561186d81612073565b809150509295985092959850929598565b60008060008060008060008060006101008a8c03121561189d57600080fd5b89356118a881612073565b985060208a01356118b881612073565b975060408a01356118c881612073565b965060608a01356118d881612073565b955060808a0135945060a08a013567ffffffffffffffff8111156118fb57600080fd5b6119078c828d0161167e565b90955093505060c08a0135915060e08a013561186d8161208b565b6000806000806000806000806000806101208b8d03121561194257600080fd5b8a3561194d81612073565b995060208b013561195d81612073565b985060408b013561196d81612073565b975060608b013561197d81612073565b965060808b0135955060a08b013567ffffffffffffffff8111156119a057600080fd5b6119ac8d828e0161167e565b90965094505060c08b0135925060e08b01356119c78161208b565b91506101008b01356119d881612073565b809150509295989b9194979a5092959850565b600080600080600080600060e0888a031215611a0657600080fd5b8735611a1181612073565b96506020880135611a2181612073565b95506040880135611a3181612073565b94506060880135611a4181612073565b93506080880135925060a0880135915060c0880135611a5f8161208b565b8091505092959891949750929550565b600080600080600080600080610100898b031215611a8c57600080fd5b8835611a9781612073565b97506020890135611aa781612073565b96506040890135611ab781612073565b95506060890135611ac781612073565b94506080890135935060a0890135925060c0890135611ae58161208b565b915060e08901356117c381612073565b60008060008060808587031215611b0b57600080fd5b8435611b1681612073565b93506020850135611b2681612073565b92506040850135611b3681612073565b9396929550929360600135925050565b600080600080600060a08688031215611b5e57600080fd5b8535611b6981612073565b94506020860135611b7981612073565b93506040860135611b8981612073565b9250606086013591506080860135611ba081612073565b809150509295509295909350565b600080600080600060808688031215611bc657600080fd5b8535611bd181612073565b94506020860135611be181612073565b935060408601359250606086013567ffffffffffffffff811115611c0457600080fd5b611c108882890161167e565b969995985093965092949392505050565b600080600080600080600080600060c08a8c031215611c3f57600080fd5b8935611c4a81612073565b985060208a013567ffffffffffffffff80821115611c6757600080fd5b611c738d838e0161167e565b909a50985060408c0135915080821115611c8c57600080fd5b611c988d838e0161167e565b909850965060608c0135915080821115611cb157600080fd5b50611cbe8c828d0161167e565b90955093505060808a0135611cd281612073565b915060a08a013561186d81612073565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a8682870161167e565b9094509250506020840135611d2e81612073565b809150509250925092565b60006020808385031215611d4c57600080fd5b825167ffffffffffffffff80821115611d6457600080fd5b818501915085601f830112611d7857600080fd5b815181811115611d8a57611d8a61205d565b8060051b604051601f19603f83011681018181108582111715611daf57611daf61205d565b604052828152858101935084860182860187018a1015611dce57600080fd5b600095505b83861015611df1578051855260019590950194938601938601611dd3565b5098975050505050505050565b600060208284031215611e1057600080fd5b8151610f0c8161208b565b600060208284031215611e2d57600080fd5b5051919050565b60008251611e46818460208701611fea565b9190910192915050565b6020815260008251806020840152611e6f816040850160208701611fea565b601f01601f19169190910160400192915050565b6020808252600d908201526c125b9d985b1a59081d985d5b1d609a1b604082015260600190565b6020808252600c908201526b496e76616c6964207361766560a01b604082015260600190565b6020808252600e908201526d125b9d985b1a59081b505cdcd95d60921b604082015260600190565b85815260806020808301829052908201859052600090869060a08401835b88811015611f44578335611f2981612073565b6001600160a01b031682529282019290820190600101611f16565b506001600160a01b03969096166040850152505050606001529392505050565b6000604082018483526020604081850152818551808452606086019150828701935060005b81811015611fae5784516001600160a01b031683529383019391830191600101611f89565b5090979650505050505050565b60008219821115611fce57611fce612031565b500190565b600082821015611fe557611fe5612031565b500390565b60005b83811015612005578181015183820152602001611fed565b8381111561030c5750506000910152565b600060001982141561202a5761202a612031565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461208857600080fd5b50565b801515811461208857600080fdfea2646970667358221220f4bd9ed4bb7fa03581f0613378a49a1f8b9727170880e2e4575e1c249b54c9ad64736f6c63430008060033

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

000000000000000000000000afce80b19a8ce13dec0739a1aab7a028d6845eb3

-----Decoded View---------------
Arg [0] : _nexus (address): 0xAFcE80b19A8cE13DEc0739a1aaB7A028d6845Eb3

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


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

OVERVIEW

Aggregates mAsset operations like mint, save, stake and buy using Uniswap or Curve.

Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.

Validator Index Block Amount
View All Withdrawals

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

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