Contract Overview
My Name Tag:
Not Available, login to update
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0x35f99db3B53cC358F6FdF2ed89193ADeB1DccE96
Contract Name:
VaultFactory
Compiler Version
v0.8.4+commit.c7e474f2
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; interface IRouter { struct RouteInfo { address router; address[] path; } function getSwapRoute(address _fromToken, address _toToken) external view returns (address _router, address[] memory _path); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "../../interfaces/IUniswapV2Pair.sol"; import "../../interfaces/IRouter.sol"; import "../VaultBase.sol"; import "./IQuickswapStakingRewards.sol"; contract VaultQuickswapLP is VaultBase { using SafeERC20 for IERC20; IQuickswapStakingRewards public stakingRewards; address public token0; address public token1; address public rewardToken; address public liquidityRouter; mapping(address => mapping(address => RouteInfo)) public routes; uint256 public swapTimeout; // hardcoded when deploy constructor(address _liquidityRouter, IQuickswapStakingRewards _stakingRewards) VaultBase() { liquidityRouter = _liquidityRouter; stakingRewards = _stakingRewards; wantAddress = stakingRewards.stakingToken(); rewardToken = stakingRewards.rewardsToken(); token0 = IUniswapV2Pair(wantAddress).token0(); token1 = IUniswapV2Pair(wantAddress).token1(); _syncSwapRoutes(); } // ========== views ================= function balanceInFarm() public view override returns (uint256) { return stakingRewards.balanceOf(address(this)); } function pending() public view override returns (uint256) { return stakingRewards.earned(address(this)); } // Main want token compounding function function compound() external override onlyHarvestor { // Harvest farm tokens uint256 _initBalance = balanceInFarm(); stakingRewards.getReward(); if (_isWETH(rewardToken)) { _wrapETH(); } // Converts farm tokens into want tokens uint256 earnedAmt = IERC20(rewardToken).balanceOf(address(this)); if (rewardToken != token0) { _swap(rewardToken, token0, earnedAmt / 2); } if (rewardToken != token1) { _swap(rewardToken, token1, earnedAmt / 2); } IERC20 _token0 = IERC20(token0); IERC20 _token1 = IERC20(token1); // Get want tokens, ie. add liquidity uint256 token0Amt = _token0.balanceOf(address(this)); uint256 token1Amt = _token1.balanceOf(address(this)); if (token0Amt > 0 && token1Amt > 0) { _token0.safeIncreaseAllowance(liquidityRouter, token0Amt); _token1.safeIncreaseAllowance(liquidityRouter, token1Amt); IUniswapV2Router(liquidityRouter).addLiquidity( token0, token1, token0Amt, token1Amt, 0, 0, address(this), block.timestamp + swapTimeout ); } lastEarnBlock = block.number; _depositToFarm(); _cleanUp(); uint256 _afterBalance = balanceInFarm(); if (_afterBalance > _initBalance) { emit Earned(wantAddress, _afterBalance - _initBalance); } else { emit Earned(wantAddress, 0); } } function deposit(uint256 _wantAmt) public override nonReentrant returns (uint256) { IERC20(wantAddress).safeTransferFrom(address(msg.sender), address(this), _wantAmt); _depositToFarm(); return _wantAmt; } function claimRewards() external override onlyOwner { stakingRewards.getReward(); uint256 _balance = IERC20(rewardToken).balanceOf(address(this)); if (_balance > 0) { IERC20(rewardToken).safeTransfer(msg.sender, _balance); } } function withdrawAll() external override onlyOwner returns (uint256 _withdrawBalance) { _exit(); _cleanUp(); _withdrawFromVault(); emit Exit(_withdrawBalance); } function withdraw(uint256 _wantAmt) public override onlyOwner nonReentrant returns (uint256) { require(_wantAmt > 0, "_wantAmt <= 0"); _widthdrawFromFarm(_wantAmt); uint256 _balance = IERC20(rewardToken).balanceOf(address(this)); _withdrawFromVault(); return _balance; } function abandon() external override onlyOwner { require(canAbandon(), "Vault cannot be abandoned"); abandoned = true; } function syncSwapRoutes() external onlyOwner { _syncSwapRoutes(); } function canAbandon() public view override returns (bool) { bool _noRewardTokenLeft = IERC20(rewardToken).balanceOf(address(this)) == 0; bool _noLpTokenLeft = IERC20(wantAddress).balanceOf(address(this)) == 0; bool _noPending = pending() == 0; return _noRewardTokenLeft && _noLpTokenLeft && _noPending; } function info() external view virtual override returns ( uint256 _templateId, uint256 _balanceInFarm, uint256 _pendingRewards, bool _abandoned, bool _canDeposit, bool _canAbandon ) { IVaultPolicy policy = getPolicy(); _templateId = templateId; _balanceInFarm = balanceInFarm(); _pendingRewards = pending(); _canDeposit = policy.canDeposit(address(this), owner); _canAbandon = canAbandon(); _abandoned = abandoned; } // ============= internal functions ================ function _syncSwapRoutes() internal override { _addRouteInfo(rewardToken, token0); _addRouteInfo(rewardToken, token1); _addRouteInfo(token0, rewardToken); _addRouteInfo(token1, rewardToken); } function _addRouteInfo(address _from, address _to) internal { if (_from != _to) { IRouter router = getRouter(); (address _router, address[] memory _path) = router.getSwapRoute(_from, _to); require(_from != address(0), "Src token is invalid"); require(_to != address(0), "Dst token is invalid"); require(_router != address(0), "Router is invalid"); require(_path[0] == _from, "Route must start with src token"); require(_path[_path.length - 1] == _to, "Route must end with dst token"); routes[_from][_to] = RouteInfo(_router, _path); } } function _getSwapRoute(address _fromToken, address _toToken) internal view returns (address _router, address[] memory _path) { RouteInfo storage _info = routes[_fromToken][_toToken]; _router = _info.router; _path = _info.path; } function _withdrawFromVault() internal { uint256 _dustRewardBal = IERC20(rewardToken).balanceOf(address(this)); if (_dustRewardBal > 0) { IERC20(rewardToken).safeTransfer(msg.sender, _dustRewardBal); } uint256 _wantBalance = IERC20(wantAddress).balanceOf(address(this)); if (_wantBalance > 0) { IERC20(wantAddress).safeTransfer(msg.sender, _wantBalance); } } function _cleanUp() internal { // Converts dust tokens into earned tokens, which will be reinvested on the next earn(). // Converts token0 dust (if any) to earned tokens uint256 token0Amt = IERC20(token0).balanceOf(address(this)); if (token0 != rewardToken && token0Amt > 0) { _swap(token0, rewardToken, token0Amt); } // Converts token1 dust (if any) to earned tokens uint256 token1Amt = IERC20(token1).balanceOf(address(this)); if (token1 != rewardToken && token1Amt > 0) { _swap(token1, rewardToken, token1Amt); } } function _depositToFarm() internal canDeposit { IERC20 wantToken = IERC20(wantAddress); uint256 wantAmt = wantToken.balanceOf(address(this)); wantToken.safeIncreaseAllowance(address(stakingRewards), wantAmt); stakingRewards.stake(wantAmt); emit Deposited(wantAmt); } function _widthdrawFromFarm(uint256 _wantAmt) internal { stakingRewards.withdraw(_wantAmt); emit Withdraw(_wantAmt); } function _exit() internal { stakingRewards.exit(); } function _swap( address _inputToken, address _outputToken, uint256 _inputAmount ) internal { if (_inputAmount == 0) { return; } (address _router, address[] memory _path) = _getSwapRoute(_inputToken, _outputToken); require(_router != address(0), "invalid route"); require(_path[0] == _inputToken, "Route must start with src token"); require(_path[_path.length - 1] == _outputToken, "Route must end with dst token"); IERC20(_inputToken).safeApprove(_router, 0); IERC20(_inputToken).safeApprove(_router, _inputAmount); _safeSwap(_router, _inputAmount, slippage, _path, address(this), block.timestamp + swapTimeout); } }
// SPDX-License-Identifier: MIT // solhint-disable-next-line compiler-version pragma solidity ^0.8.0; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { require(_initializing || !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
// 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' // solhint-disable-next-line max-line-length 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 // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor () { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; interface IUniswapV2Pair { function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "../interfaces/IVault.sol"; import "../interfaces/IVaultPolicy.sol"; import "../interfaces/IVaultFactory.sol"; import "../interfaces/IUniswapV2Router.sol"; import "../interfaces/IRouter.sol"; import "../interfaces/IWETH.sol"; abstract contract VaultBase is IVault, ReentrancyGuard { using SafeERC20 for IERC20; struct RouteInfo { address router; address[] path; } uint256 internal constant RATIO_PRECISION = 1000000; // 6 decimals address internal constant weth = 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270; // matic // =========== state variables ================================ bool public initialized; IVaultFactory public factory; address public override owner; // the only address can deposit, withdraw address public harvestor; // this address can call earn method uint256 public lastEarnBlock; address public override wantAddress; bool public override abandoned; uint256 public slippage = 50000; // 0.5% uint256 public templateId; // =========== events ================================ event Earned(address indexed _earnedToken, uint256 _amount); event Deposited(uint256 _amount); event Withdraw(uint256 _amount); event Exit(uint256 _lpAmount); // =========== constructor =========================== constructor() { factory = IVaultFactory(msg.sender); } function initialize(address _owner, uint256 _vaultTemplateId) external virtual override { require(!initialized, "already init"); require(msg.sender == address(factory), "!factory"); harvestor = _owner; owner = _owner; templateId = _vaultTemplateId; _syncSwapRoutes(); initialized = true; } // =========== views =============================== function canAbandon() public view virtual override returns (bool); function info() external view virtual override returns ( uint256 _templateId, uint256 _balanceInFarm, uint256 _pendingRewards, bool _abandoned, bool _canDeposit, bool _canAbandon ); function getPolicy() public view virtual returns (IVaultPolicy) { address _policy = factory.policy(); return IVaultPolicy(_policy); } function getRouter() public view virtual returns (IRouter) { address _router = factory.router(); return IRouter(_router); } // =========== modifiers =========================== modifier onlyOwner() { require(msg.sender == owner, "!owner"); _; } modifier onlyHarvestor() { require(msg.sender == harvestor || msg.sender == owner, "!owner && !harvestor"); _; } modifier canHarvest() { require(initialized, "!init"); _; } modifier canDeposit() { require(initialized, "!init"); IVaultPolicy policy = getPolicy(); require(policy.canDeposit(address(this), owner), "!canDeposit"); _; } // =========== restricted functions ================= function updateSlippage(uint256 _slippage) public virtual override onlyOwner { slippage = _slippage; } function setHarvestor(address _harvestor) external onlyOwner { require(_harvestor != address(0x0), "cannot address set to zero"); harvestor = _harvestor; } function abandon() external virtual override; function claimRewards() external virtual override; // =========== internal functions ================== function _safeSwap( address _swapRouterAddress, uint256 _amountIn, uint256 _slippage, address[] memory _path, address _to, uint256 _deadline ) internal { IUniswapV2Router _swapRouter = IUniswapV2Router(_swapRouterAddress); require(_path.length > 0, "invalidSwapPath"); uint256[] memory amounts = _swapRouter.getAmountsOut(_amountIn, _path); uint256 _minAmountOut = (amounts[amounts.length - 1] * (RATIO_PRECISION - _slippage)) / RATIO_PRECISION; _swapRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(_amountIn, _minAmountOut, _path, _to, _deadline); } function _unwrapETH() internal { // WETH -> ETH uint256 wethBalance = IERC20(weth).balanceOf(address(this)); if (wethBalance > 0) { IWETH(weth).withdraw(wethBalance); } } function _wrapETH() internal { // ETH -> WETH uint256 ethBalance = address(this).balance; if (ethBalance > 0) { IWETH(weth).deposit{value: ethBalance}(); } } function _isWETH(address _token) internal pure returns (bool) { return _token == weth; } function _syncSwapRoutes() internal virtual; // =========== emergency functions ================= function rescueFund(address _token, uint256 _amount) public virtual override onlyOwner { IERC20(_token).safeTransfer(owner, _amount); } function executeTransaction( address target, uint256 value, string memory signature, bytes memory data ) public onlyOwner returns (bytes memory) { bytes memory callData; if (bytes(signature).length == 0) { callData = data; } else { callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data); } // solium-disable-next-line security/no-call-value (bool success, bytes memory returnData) = target.call{value: value}(callData); require(success, string("DevFund::executeTransaction: Transaction execution reverted.")); return returnData; } receive() external payable {} }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; interface IQuickswapStakingRewards { function stakingToken() external view returns (address); function rewardsToken() external view returns (address); function balanceOf(address _account) external view returns (uint256); function earned(address account) external view returns (uint256); function stake(uint256 amount) external; function withdraw(uint256 amount) external; function exit() external; function getReward() external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// 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); }
// 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; // solhint-disable-next-line no-inline-assembly 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"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (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"); // solhint-disable-next-line avoid-low-level-calls (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"); // solhint-disable-next-line avoid-low-level-calls (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"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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 // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; interface IVault { function owner() external view returns (address); function wantAddress() external view returns (address); function balanceInFarm() external view returns (uint256); function pending() external view returns (uint256); function abandoned() external view returns (bool); function initialize(address _owner, uint256 _vaultTemplateId) external; function compound() external; function abandon() external; function claimRewards() external; function deposit(uint256 _wantAmt) external returns (uint256); function withdraw(uint256 _wantAmt) external returns (uint256); function withdrawAll() external returns (uint256); function updateSlippage(uint256 _slippage) external; function rescueFund(address _token, uint256 _amount) external; function canAbandon() external returns (bool); function info() external view returns ( uint256 _templateId, uint256 _balanceInFarm, uint256 _pendingRewards, bool _abandoned, bool _canDeposit, bool _canAbandon ); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; interface IVaultPolicy { function canDeposit(address _strategy, address _owner) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; interface IVaultFactory { function policy() external view returns (address); function router() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; interface IUniswapV2Router { function factory() external pure returns (address); function WBNB() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityBNB( address token, uint amountTokenDesired, uint amountTokenMin, uint amountBNBMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountBNB, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityBNB( address token, uint liquidity, uint amountTokenMin, uint amountBNBMin, address to, uint deadline ) external returns (uint amountToken, uint amountBNB); function removeLiquidityWithPermit( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityBNBWithPermit( address token, uint liquidity, uint amountTokenMin, uint amountBNBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountBNB); function removeLiquidityBNBSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountBNBMin, address to, uint deadline ) external returns (uint amountBNB); function removeLiquidityBNBWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountBNBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountBNB); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactBNBForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, address to, uint deadline ) external payable; function swapExactTokensForBNBSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactBNBForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactBNB(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForBNB(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapBNBForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IWETH is IERC20 { function deposit() external payable; function withdraw(uint256 wad) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "../../interfaces/IUniswapV2Pair.sol"; import "../../interfaces/IRouter.sol"; import "../VaultBase.sol"; import "./IMasterChefIron.sol"; contract VaultIronLP is VaultBase { using SafeERC20 for IERC20; IMasterChefIron public masterChef; address public token0; address public token1; address public rewardToken; uint256 public poolId; address public liquidityRouter; mapping(address => mapping(address => RouteInfo)) public routes; uint256 public swapTimeout; // hardcoded when deploy constructor( address _liquidityRouter, IMasterChefIron _masterChef, uint256 _poolId ) VaultBase() { liquidityRouter = _liquidityRouter; poolId = _poolId; masterChef = _masterChef; (wantAddress, , , ) = _masterChef.poolInfo(poolId); rewardToken = _masterChef.rewardToken(); token0 = IUniswapV2Pair(wantAddress).token0(); token1 = IUniswapV2Pair(wantAddress).token1(); _syncSwapRoutes(); } // ========== views ================= function balanceInFarm() public view override returns (uint256) { (uint256 _amount, ) = masterChef.userInfo(poolId, address(this)); return _amount; } function pending() public view override returns (uint256) { return masterChef.pendingReward(poolId, address(this)); } function canAbandon() public view override returns (bool) { bool _noRewardTokenLeft = IERC20(rewardToken).balanceOf(address(this)) == 0; bool _noLpTokenLeft = IERC20(wantAddress).balanceOf(address(this)) == 0; bool _noPending = pending() == 0; return _noRewardTokenLeft && _noLpTokenLeft && _noPending; } function info() external view virtual override returns ( uint256 _templateId, uint256 _balanceInFarm, uint256 _pendingRewards, bool _abandoned, bool _canDeposit, bool _canAbandon ) { IVaultPolicy policy = getPolicy(); _templateId = templateId; _balanceInFarm = balanceInFarm(); _pendingRewards = pending(); _canDeposit = policy.canDeposit(address(this), owner); _canAbandon = canAbandon(); _abandoned = abandoned; } // ========== vault core functions =========== function compound() external override onlyHarvestor { // Harvest farm tokens uint256 _initBalance = balanceInFarm(); _widthdrawFromFarm(0); if (_isWETH(rewardToken)) { _wrapETH(); } // Converts farm tokens into want tokens uint256 earnedAmt = IERC20(rewardToken).balanceOf(address(this)); if (rewardToken != token0) { _swap(rewardToken, token0, earnedAmt / 2); } if (rewardToken != token1) { _swap(rewardToken, token1, earnedAmt / 2); } IERC20 _token0 = IERC20(token0); IERC20 _token1 = IERC20(token1); // Get want tokens, ie. add liquidity uint256 token0Amt = _token0.balanceOf(address(this)); uint256 token1Amt = _token1.balanceOf(address(this)); if (token0Amt > 0 && token1Amt > 0) { _token0.safeIncreaseAllowance(liquidityRouter, token0Amt); _token1.safeIncreaseAllowance(liquidityRouter, token1Amt); IUniswapV2Router(liquidityRouter).addLiquidity( token0, token1, token0Amt, token1Amt, 0, 0, address(this), block.timestamp + swapTimeout ); } lastEarnBlock = block.number; _depositToFarm(); _cleanUp(); uint256 _afterBalance = balanceInFarm(); if (_afterBalance > _initBalance) { emit Earned(wantAddress, _afterBalance - _initBalance); } else { emit Earned(wantAddress, 0); } } function deposit(uint256 _wantAmt) public override nonReentrant returns (uint256) { IERC20(wantAddress).safeTransferFrom(address(msg.sender), address(this), _wantAmt); _depositToFarm(); return _wantAmt; } function withdrawAll() external override onlyOwner returns (uint256 _withdrawBalance) { uint256 _balance = balanceInFarm(); _withdrawBalance = withdraw(_balance); _cleanUp(); _withdrawFromVault(); emit Exit(_withdrawBalance); } function withdraw(uint256 _wantAmt) public override onlyOwner nonReentrant returns (uint256) { require(_wantAmt > 0, "_wantAmt <= 0"); _widthdrawFromFarm(_wantAmt); uint256 _balance = IERC20(rewardToken).balanceOf(address(this)); _withdrawFromVault(); return _balance; } function claimRewards() external override onlyOwner { _widthdrawFromFarm(0); uint256 _balance = IERC20(rewardToken).balanceOf(address(this)); if (_balance > 0) { IERC20(rewardToken).safeTransfer(msg.sender, _balance); } } function abandon() external override onlyOwner { require(canAbandon(), "Vault cannot be abandoned"); abandoned = true; } function syncSwapRoutes() external onlyOwner { _syncSwapRoutes(); } // ============= internal functions ================ function _syncSwapRoutes() internal override { _addRouteInfo(rewardToken, token0); _addRouteInfo(rewardToken, token1); _addRouteInfo(token0, rewardToken); _addRouteInfo(token1, rewardToken); } function _addRouteInfo(address _from, address _to) internal { if (_from != _to) { IRouter router = getRouter(); (address _router, address[] memory _path) = router.getSwapRoute(_from, _to); require(_from != address(0), "Src token is invalid"); require(_to != address(0), "Dst token is invalid"); require(_router != address(0), "Router is invalid"); require(_path[0] == _from, "Route must start with src token"); require(_path[_path.length - 1] == _to, "Route must end with dst token"); routes[_from][_to] = RouteInfo(_router, _path); } } function _getSwapRoute(address _fromToken, address _toToken) internal view returns (address _router, address[] memory _path) { RouteInfo storage _info = routes[_fromToken][_toToken]; _router = _info.router; _path = _info.path; } function _withdrawFromVault() internal { uint256 _dustRewardBal = IERC20(rewardToken).balanceOf(address(this)); if (_dustRewardBal > 0) { IERC20(rewardToken).safeTransfer(msg.sender, _dustRewardBal); } uint256 _wantBalance = IERC20(wantAddress).balanceOf(address(this)); if (_wantBalance > 0) { IERC20(wantAddress).safeTransfer(msg.sender, _wantBalance); } } function _cleanUp() internal { // Converts dust tokens into earned tokens, which will be reinvested on the next earn(). // Converts token0 dust (if any) to earned tokens uint256 token0Amt = IERC20(token0).balanceOf(address(this)); if (token0 != rewardToken && token0Amt > 0) { _swap(token0, rewardToken, token0Amt); } // Converts token1 dust (if any) to earned tokens uint256 token1Amt = IERC20(token1).balanceOf(address(this)); if (token1 != rewardToken && token1Amt > 0) { _swap(token1, rewardToken, token1Amt); } } function _depositToFarm() internal canDeposit { IERC20 wantToken = IERC20(wantAddress); uint256 wantAmt = wantToken.balanceOf(address(this)); wantToken.safeIncreaseAllowance(address(masterChef), wantAmt); masterChef.deposit(poolId, wantAmt); emit Deposited(wantAmt); } function _widthdrawFromFarm(uint256 _wantAmt) internal { masterChef.withdraw(poolId, _wantAmt); emit Withdraw(_wantAmt); } function _swap( address _inputToken, address _outputToken, uint256 _inputAmount ) internal { if (_inputAmount == 0) { return; } (address _router, address[] memory _path) = _getSwapRoute(_inputToken, _outputToken); require(_router != address(0), "invalid route"); require(_path[0] == _inputToken, "Route must start with src token"); require(_path[_path.length - 1] == _outputToken, "Route must end with dst token"); IERC20(_inputToken).safeApprove(_router, 0); IERC20(_inputToken).safeApprove(_router, _inputAmount); _safeSwap(_router, _inputAmount, slippage, _path, address(this), block.timestamp + swapTimeout); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; interface IMasterChefIron { function poolInfo(uint256 poolId) external view returns ( address lpToken, uint256 allocPoint, uint256 lastRewardBlock, uint256 accRewardPerShare ); function userInfo(uint256 poolId, address user) external view returns (uint256 amount, uint256 debt); function pendingReward(uint256 _pid, address _user) external view returns (uint256); function deposit(uint256 poolId, uint256 amount) external; function withdraw(uint256 poolId, uint256 amount) external; function rewardToken() external view returns (address); function add( uint256 _allocPoint, address _lpToken, bool _withUpdate ) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import "./interfaces/IVault.sol"; contract VaultFactory is Ownable, Initializable { struct VaultTemplate { bytes code; bytes arguments; } VaultTemplate[] public vaultTemplates; mapping(address => address[]) public userVaults; address public policy; address public router; // EVENTS event PolicySet(address _policy); event RouterSet(address _policy); event VaultAdded(address indexed _owner, address _vault); // CONSTRUCTORS function initialize(address _policy, address _router) external onlyOwner initializer { policy = _policy; router = _router; } // PUBLIC FUNCTIONS function getUserVaults(address _user) external view returns (address[] memory) { return userVaults[_user]; } function createVault(uint256 _templateId) external returns (address _vault) { VaultTemplate storage _template = vaultTemplates[_templateId]; bytes memory bytecode = _template.code; require(bytecode.length != 0, "vault is not supported"); bytes memory arguments = _template.arguments; require(arguments.length != 0, "invalid vault arguments"); bytecode = abi.encodePacked(bytecode, arguments); bytes32 salt = keccak256(abi.encodePacked(msg.sender, arguments, block.number)); // solhint-disable no-inline-assembly assembly { _vault := create2(0, add(bytecode, 0x20), mload(bytecode), salt) if iszero(extcodesize(_vault)) { revert(0, 0) } } IVault(_vault).initialize(msg.sender, _templateId); userVaults[msg.sender].push(_vault); emit VaultAdded(msg.sender, _vault); } // RESTRICTER FUNCTION function setPolicy(address _policy) external onlyOwner { require(_policy != address(0x0), "emptyAddress"); require(_policy != policy, "unchanged"); policy = _policy; emit PolicySet(_policy); } function setRouter(address _router) external onlyOwner { require(_router != address(0x0), "emptyAddress"); require(_router != router, "unchanged"); router = _router; emit RouterSet(_router); } function addTemplate(bytes calldata _code, bytes calldata _initArguments) external onlyOwner { VaultTemplate memory _template = VaultTemplate(_code, _initArguments); vaultTemplates.push(_template); } function removeTemplate(uint256 tid) external onlyOwner { vaultTemplates[tid] = VaultTemplate("", ""); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import "@openzeppelin/contracts/access/Ownable.sol"; import "./interfaces/IRouter.sol"; contract Router is IRouter, Ownable { mapping(address => mapping(address => RouteInfo)) public routes; function addRoute( address _from, address _to, address _router, address[] calldata path ) external onlyOwner { require(_from != address(0), "Src token is invalid"); require(_to != address(0), "Dst token is invalid"); require(_from != _to, "Src token must be diff from Dst token"); require(_router != address(0), "Router is invalid"); require(path[0] == _from, "Route must start with src token"); require(path[path.length - 1] == _to, "Route must end with dst token"); RouteInfo memory _info = RouteInfo(_router, path); routes[_from][_to] = _info; } function removeRoute(address _from, address _to) external onlyOwner { address[] memory _empty; routes[_from][_to] = RouteInfo(address(0), _empty); } function getSwapRoute(address _fromToken, address _toToken) external view override returns (address _router, address[] memory _path) { RouteInfo storage _info = routes[_fromToken][_toToken]; _router = _info.router; _path = _info.path; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import "@openzeppelin/contracts/access/Ownable.sol"; import "../interfaces/IVaultPolicy.sol"; contract VaultPolicy is IVaultPolicy, Ownable { function canDeposit(address, address) external pure override returns (bool) { return true; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../interfaces/IUniswapV2Router.sol"; import "../interfaces/IWETH.sol"; library VaultLib { uint256 private constant RATIO_PRECISION = 1000000; // 6 decimals address private constant weth = 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270; function safeSwap( address _swapRouterAddress, uint256 _amountIn, uint256 _slippage, address[] memory _path, address _to, uint256 _deadline ) internal { IUniswapV2Router _swapRouter = IUniswapV2Router(_swapRouterAddress); require(_path.length > 0, "invalidSwapPath"); uint256[] memory amounts = _swapRouter.getAmountsOut(_amountIn, _path); uint256 _minAmountOut = (amounts[amounts.length - 1] * (RATIO_PRECISION - _slippage)) / RATIO_PRECISION; _swapRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens( _amountIn, _minAmountOut, _path, _to, _deadline ); } function unwrapETH() internal { // WETH -> ETH uint256 wethBalance = IERC20(weth).balanceOf(address(this)); if (wethBalance > 0) { IWETH(weth).withdraw(wethBalance); } } function wrapETH() internal { // ETH -> WETH uint256 ethBalance = address(this).balance; if (ethBalance > 0) { IWETH(weth).deposit{value: ethBalance}(); } } function isWETH(address _token) internal pure returns (bool) { return _token == weth; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "metadata": { "useLiteralContent": true } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_policy","type":"address"}],"name":"PolicySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_policy","type":"address"}],"name":"RouterSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":false,"internalType":"address","name":"_vault","type":"address"}],"name":"VaultAdded","type":"event"},{"inputs":[{"internalType":"bytes","name":"_code","type":"bytes"},{"internalType":"bytes","name":"_initArguments","type":"bytes"}],"name":"addTemplate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_templateId","type":"uint256"}],"name":"createVault","outputs":[{"internalType":"address","name":"_vault","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getUserVaults","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_policy","type":"address"},{"internalType":"address","name":"_router","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"policy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tid","type":"uint256"}],"name":"removeTemplate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_policy","type":"address"}],"name":"setPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"}],"name":"setRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userVaults","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vaultTemplates","outputs":[{"internalType":"bytes","name":"code","type":"bytes"},{"internalType":"bytes","name":"arguments","type":"bytes"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35061119d806100616000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80639c841fef1161008c578063c60c802e11610066578063c60c802e146101cd578063e7f3c69c146101e0578063f2fde38b14610200578063f887ea401461021357600080fd5b80639c841fef14610194578063c04d0ab7146101a7578063c0d78655146101ba57600080fd5b8063715018a6116100c8578063715018a6146101555780637d4163d31461015d5780638da5cb5b146101705780639abbdf4b1461018157600080fd5b80630505c8c9146100ef578063388b9d7e1461011f578063485cc95514610140575b600080fd5b600354610102906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61013261012d366004610f9e565b610226565b60405161011692919061109d565b61015361014e366004610eda565b61036a565b005b610153610495565b61015361016b366004610eb9565b610509565b6000546001600160a01b0316610102565b61010261018f366004610f9e565b610617565b6101026101a2366004610f0c565b61094f565b6101536101b5366004610f9e565b610987565b6101536101c8366004610eb9565b610a44565b6101536101db366004610f35565b610b4b565b6101f36101ee366004610eb9565b610c5d565b6040516101169190611050565b61015361020e366004610eb9565b610cd3565b600454610102906001600160a01b031681565b6001818154811061023657600080fd5b90600052602060002090600202016000915090508060000180546102599061112c565b80601f01602080910402602001604051908101604052809291908181526020018280546102859061112c565b80156102d25780601f106102a7576101008083540402835291602001916102d2565b820191906000526020600020905b8154815290600101906020018083116102b557829003601f168201915b5050505050908060010180546102e79061112c565b80601f01602080910402602001604051908101604052809291908181526020018280546103139061112c565b80156103605780601f1061033557610100808354040283529160200191610360565b820191906000526020600020905b81548152906001019060200180831161034357829003601f168201915b5050505050905082565b6000546001600160a01b0316331461039d5760405162461bcd60e51b8152600401610394906110cb565b60405180910390fd5b600054600160a81b900460ff16806103bf5750600054600160a01b900460ff16155b6104225760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610394565b600054600160a81b900460ff1615801561044c576000805461ffff60a01b191661010160a01b1790555b600380546001600160a01b038086166001600160a01b03199283161790925560048054928516929091169190911790558015610490576000805460ff60a81b191690555b505050565b6000546001600160a01b031633146104bf5760405162461bcd60e51b8152600401610394906110cb565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031633146105335760405162461bcd60e51b8152600401610394906110cb565b6001600160a01b0381166105785760405162461bcd60e51b815260206004820152600c60248201526b656d7074794164647265737360a01b6044820152606401610394565b6003546001600160a01b03828116911614156105c25760405162461bcd60e51b81526020600482015260096024820152681d5b98da185b99d95960ba1b6044820152606401610394565b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527f3a2628f7ccb17cc55d501ab2ced8a94fe8b859b3ac8da6bab338668b7f135504906020015b60405180910390a150565b6000806001838154811061063b57634e487b7160e01b600052603260045260246000fd5b90600052602060002090600202019050600081600001805461065c9061112c565b80601f01602080910402602001604051908101604052809291908181526020018280546106889061112c565b80156106d55780601f106106aa576101008083540402835291602001916106d5565b820191906000526020600020905b8154815290600101906020018083116106b857829003601f168201915b505050505090508051600014156107275760405162461bcd60e51b81526020600482015260166024820152751d985d5b1d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b6044820152606401610394565b60008260010180546107389061112c565b80601f01602080910402602001604051908101604052809291908181526020018280546107649061112c565b80156107b15780601f10610786576101008083540402835291602001916107b1565b820191906000526020600020905b81548152906001019060200180831161079457829003601f168201915b5050505050905080516000141561080a5760405162461bcd60e51b815260206004820152601760248201527f696e76616c6964207661756c7420617267756d656e74730000000000000000006044820152606401610394565b818160405160200161081d929190611021565b6040516020818303038152906040529150600033824360405160200161084593929190610fe2565b604051602081830303815290604052805190602001209050808351602085016000f59450843b61087457600080fd5b60405163cd6dc68760e01b8152336004820152602481018790526001600160a01b0386169063cd6dc68790604401600060405180830381600087803b1580156108bc57600080fd5b505af11580156108d0573d6000803e3d6000fd5b505033600081815260026020908152604080832080546001810182559084529282902090920180546001600160a01b0319166001600160a01b038c1690811790915591519182529193507f2f0697414292d16e25e419060ebbb3a3318648280380829ca42af307b155393b92500160405180910390a250505050919050565b6002602052816000526040600020818154811061096b57600080fd5b6000918252602090912001546001600160a01b03169150829050565b6000546001600160a01b031633146109b15760405162461bcd60e51b8152600401610394906110cb565b6040805160608101825260008183018181528252825160208181019094529081529181019190915260018054839081106109fb57634e487b7160e01b600052603260045260246000fd5b90600052602060002090600202016000820151816000019080519060200190610a25929190610dbd565b506020828101518051610a3e9260018501920190610dbd565b50505050565b6000546001600160a01b03163314610a6e5760405162461bcd60e51b8152600401610394906110cb565b6001600160a01b038116610ab35760405162461bcd60e51b815260206004820152600c60248201526b656d7074794164647265737360a01b6044820152606401610394565b6004546001600160a01b0382811691161415610afd5760405162461bcd60e51b81526020600482015260096024820152681d5b98da185b99d95960ba1b6044820152606401610394565b600480546001600160a01b0319166001600160a01b0383169081179091556040519081527fc6b438e6a8a59579ce6a4406cbd203b740e0d47b458aae6596339bcd40c40d159060200161060c565b6000546001600160a01b03163314610b755760405162461bcd60e51b8152600401610394906110cb565b6040805160606020601f8701819004028201810183529181018581526000928291908890889081908501838280828437600092019190915250505090825250604080516020601f8701819004810282018101909252858152918101919086908690819084018382808284376000920182905250939094525050600180548082018255915282518051939450849360029092027fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6019250610c3a91839160200190610dbd565b506020828101518051610c539260018501920190610dbd565b5050505050505050565b6001600160a01b038116600090815260026020908152604091829020805483518184028101840190945280845260609392830182828015610cc757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ca9575b50505050509050919050565b6000546001600160a01b03163314610cfd5760405162461bcd60e51b8152600401610394906110cb565b6001600160a01b038116610d625760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610394565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b828054610dc99061112c565b90600052602060002090601f016020900481019282610deb5760008555610e31565b82601f10610e0457805160ff1916838001178555610e31565b82800160010185558215610e31579182015b82811115610e31578251825591602001919060010190610e16565b50610e3d929150610e41565b5090565b5b80821115610e3d5760008155600101610e42565b80356001600160a01b0381168114610e6d57600080fd5b919050565b60008083601f840112610e83578182fd5b50813567ffffffffffffffff811115610e9a578182fd5b602083019150836020828501011115610eb257600080fd5b9250929050565b600060208284031215610eca578081fd5b610ed382610e56565b9392505050565b60008060408385031215610eec578081fd5b610ef583610e56565b9150610f0360208401610e56565b90509250929050565b60008060408385031215610f1e578182fd5b610f2783610e56565b946020939093013593505050565b60008060008060408587031215610f4a578182fd5b843567ffffffffffffffff80821115610f61578384fd5b610f6d88838901610e72565b90965094506020870135915080821115610f85578384fd5b50610f9287828801610e72565b95989497509550505050565b600060208284031215610faf578081fd5b5035919050565b60008151808452610fce816020860160208601611100565b601f01601f19169290920160200192915050565b6bffffffffffffffffffffffff198460601b1681526000835161100c816014850160208801611100565b60149201918201929092526034019392505050565b60008351611033818460208801611100565b835190830190611047818360208801611100565b01949350505050565b6020808252825182820181905260009190848201906040850190845b818110156110915783516001600160a01b03168352928401929184019160010161106c565b50909695505050505050565b6040815260006110b06040830185610fb6565b82810360208401526110c28185610fb6565b95945050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60005b8381101561111b578181015183820152602001611103565b83811115610a3e5750506000910152565b600181811c9082168061114057607f821691505b6020821081141561116157634e487b7160e01b600052602260045260246000fd5b5091905056fea2646970667358221220bb832dfbf341d571e5795e85faa4eb3ebd2d7d87f8cb807eeee5cd66e1acbaaa64736f6c63430008040033
Deployed ByteCode Sourcemap
209:2533:9:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;438:21;;;;;-1:-1:-1;;;;;438:21:9;;;;;;-1:-1:-1;;;;;3646:32:24;;;3628:51;;3616:2;3601:18;438:21:9;;;;;;;;342:37;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;668:144::-;;;;;;:::i;:::-;;:::i;:::-;;1700:145:0;;;:::i;1931:228:9:-;;;;;;:::i;:::-;;:::i;1068:85:0:-;1114:7;1140:6;-1:-1:-1;;;;;1140:6:0;1068:85;;969:928:9;;;;;;:::i;:::-;;:::i;385:47::-;;;;;;:::i;:::-;;:::i;2624:116::-;;;;;;:::i;:::-;;:::i;2165:228::-;;;;;;:::i;:::-;;:::i;2399:219::-;;;;;;:::i;:::-;;:::i;843:120::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;1994:240:0:-;;;;;;:::i;:::-;;:::i;465:21:9:-;;;;;-1:-1:-1;;;;;465:21:9;;;342:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;668:144::-;1114:7:0;1140:6;-1:-1:-1;;;;;1140:6:0;665:10:7;1280:23:0;1272:68;;;;-1:-1:-1;;;1272:68:0;;;;;;;:::i;:::-;;;;;;;;;1456:13:1::1;::::0;-1:-1:-1;;;1456:13:1;::::1;;;::::0;:30:::1;;-1:-1:-1::0;1474:12:1::1;::::0;-1:-1:-1;;;1474:12:1;::::1;;;1473:13;1456:30;1448:89;;;::::0;-1:-1:-1;;;1448:89:1;;5977:2:24;1448:89:1::1;::::0;::::1;5959:21:24::0;6016:2;5996:18;;;5989:30;6055:34;6035:18;;;6028:62;-1:-1:-1;;;6106:18:24;;;6099:44;6160:19;;1448:89:1::1;5949:236:24::0;1448:89:1::1;1548:19;1571:13:::0;-1:-1:-1;;;1571:13:1;::::1;;;1570:14;1594:98:::0;::::1;;;1628:13;:20:::0;;-1:-1:-1;;;;1662:19:1;-1:-1:-1;;;1662:19:1;;;1594:98:::1;763:6:9::2;:16:::0;;-1:-1:-1;;;;;763:16:9;;::::2;-1:-1:-1::0;;;;;;763:16:9;;::::2;;::::0;;;789:6:::2;:16:::0;;;;::::2;::::0;;;::::2;::::0;;;::::2;::::0;;1714:66:1;::::1;;;1764:5;1748:21:::0;;-1:-1:-1;;;;1748:21:1::1;::::0;;1714:66:::1;1350:1:0;668:144:9::0;;:::o;1700:145:0:-;1114:7;1140:6;-1:-1:-1;;;;;1140:6:0;665:10:7;1280:23:0;1272:68;;;;-1:-1:-1;;;1272:68:0;;;;;;;:::i;:::-;1806:1:::1;1790:6:::0;;1769:40:::1;::::0;-1:-1:-1;;;;;1790:6:0;;::::1;::::0;1769:40:::1;::::0;1806:1;;1769:40:::1;1836:1;1819:19:::0;;-1:-1:-1;;;;;;1819:19:0::1;::::0;;1700:145::o;1931:228:9:-;1114:7:0;1140:6;-1:-1:-1;;;;;1140:6:0;665:10:7;1280:23:0;1272:68;;;;-1:-1:-1;;;1272:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;2004:23:9;::::1;1996:48;;;::::0;-1:-1:-1;;;1996:48:9;;7442:2:24;1996:48:9::1;::::0;::::1;7424:21:24::0;7481:2;7461:18;;;7454:30;-1:-1:-1;;;7500:18:24;;;7493:42;7552:18;;1996:48:9::1;7414:162:24::0;1996:48:9::1;2073:6;::::0;-1:-1:-1;;;;;2062:17:9;;::::1;2073:6:::0;::::1;2062:17;;2054:39;;;::::0;-1:-1:-1;;;2054:39:9;;6392:2:24;2054:39:9::1;::::0;::::1;6374:21:24::0;6431:1;6411:18;;;6404:29;-1:-1:-1;;;6449:18:24;;;6442:39;6498:18;;2054:39:9::1;6364:158:24::0;2054:39:9::1;2103:6;:16:::0;;-1:-1:-1;;;;;;2103:16:9::1;-1:-1:-1::0;;;;;2103:16:9;::::1;::::0;;::::1;::::0;;;2134:18:::1;::::0;3628:51:24;;;2134:18:9::1;::::0;3616:2:24;3601:18;2134::9::1;;;;;;;;1931:228:::0;:::o;969:928::-;1029:14;1055:31;1089:14;1104:11;1089:27;;;;;;-1:-1:-1;;;1089:27:9;;;;;;;;;;;;;;;;;;;1055:61;;1126:21;1150:9;:14;;1126:38;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1182:8;:15;1201:1;1182:20;;1174:55;;;;-1:-1:-1;;;1174:55:9;;5219:2:24;1174:55:9;;;5201:21:24;5258:2;5238:18;;;5231:30;-1:-1:-1;;;5277:18:24;;;5270:52;5339:18;;1174:55:9;5191:172:24;1174:55:9;1239:22;1264:9;:19;;1239:44;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1301:9;:16;1321:1;1301:21;;1293:57;;;;-1:-1:-1;;;1293:57:9;;7090:2:24;1293:57:9;;;7072:21:24;7129:2;7109:18;;;7102:30;7168:25;7148:18;;;7141:53;7211:18;;1293:57:9;7062:173:24;1293:57:9;1389:8;1399:9;1372:37;;;;;;;;;:::i;:::-;;;;;;;;;;;;;1361:48;;1419:12;1461:10;1473:9;1484:12;1444:53;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;1434:64;;;;;;1419:79;;1637:4;1626:8;1620:15;1613:4;1603:8;1599:19;1596:1;1588:54;1578:64;;1677:6;1665:19;1655:2;;1714:1;1711;1704:12;1655:2;1750:50;;-1:-1:-1;;;1750:50:9;;1776:10;1750:50;;;3864:51:24;3931:18;;;3924:34;;;-1:-1:-1;;;;;1750:25:9;;;;;3837:18:24;;1750:50:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1821:10:9;1810:22;;;;:10;:22;;;;;;;;:35;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;1810:35:9;-1:-1:-1;;;;;1810:35:9;;;;;;;;1860:30;;3628:51:24;;;1821:10:9;;-1:-1:-1;1860:30:9;;-1:-1:-1;3601:18:24;1860:30:9;;;;;;;969:928;;;;;;;:::o;385:47::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;385:47:9;;-1:-1:-1;385:47:9;;-1:-1:-1;385:47:9:o;2624:116::-;1114:7:0;1140:6;-1:-1:-1;;;;;1140:6:0;665:10:7;1280:23:0;1272:68;;;;-1:-1:-1;;;1272:68:0;;;;;;;:::i;:::-;2712:21:9::1;::::0;;;;;;;-1:-1:-1;2712:21:9;;::::1;::::0;;;;;;;::::1;::::0;;::::1;::::0;;;;;;;;::::1;::::0;;;;2690:14:::1;:19:::0;;2705:3;;2690:19;::::1;;;-1:-1:-1::0;;;2690:19:9::1;;;;;;;;;;;;;;;;;;;:43;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;2690:43:9::1;::::0;;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;;;;2624:116:9:o;2165:228::-;1114:7:0;1140:6;-1:-1:-1;;;;;1140:6:0;665:10:7;1280:23:0;1272:68;;;;-1:-1:-1;;;1272:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;2238:23:9;::::1;2230:48;;;::::0;-1:-1:-1;;;2230:48:9;;7442:2:24;2230:48:9::1;::::0;::::1;7424:21:24::0;7481:2;7461:18;;;7454:30;-1:-1:-1;;;7500:18:24;;;7493:42;7552:18;;2230:48:9::1;7414:162:24::0;2230:48:9::1;2307:6;::::0;-1:-1:-1;;;;;2296:17:9;;::::1;2307:6:::0;::::1;2296:17;;2288:39;;;::::0;-1:-1:-1;;;2288:39:9;;6392:2:24;2288:39:9::1;::::0;::::1;6374:21:24::0;6431:1;6411:18;;;6404:29;-1:-1:-1;;;6449:18:24;;;6442:39;6498:18;;2288:39:9::1;6364:158:24::0;2288:39:9::1;2337:6;:16:::0;;-1:-1:-1;;;;;;2337:16:9::1;-1:-1:-1::0;;;;;2337:16:9;::::1;::::0;;::::1;::::0;;;2368:18:::1;::::0;3628:51:24;;;2368:18:9::1;::::0;3616:2:24;3601:18;2368::9::1;3583:102:24::0;2399:219:9;1114:7:0;1140:6;-1:-1:-1;;;;;1140:6:0;665:10:7;1280:23:0;1272:68;;;;-1:-1:-1;;;1272:68:0;;;;;;;:::i;:::-;2535:36:9::1;::::0;;;::::1;;::::0;::::1;::::0;;::::1;;::::0;;;;;;;;::::1;::::0;;;2502:30:::1;::::0;2535:36;;;2549:5;;;;;;2535:36;;2549:5;;;;2535:36;::::1;;::::0;::::1;::::0;;;;-1:-1:-1;;;2535:36:9;;;-1:-1:-1;2535:36:9::1;::::0;;::::1;;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;;::::1;::::0;;2556:14;;;;;;2535:36;::::1;2556:14:::0;;;;2535:36;::::1;;::::0;::::1;::::0;;;-1:-1:-1;2535:36:9;;;;-1:-1:-1;;2581:14:9::1;:30:::0;;;;::::1;::::0;;;;;;;;2502:69;;-1:-1:-1;2502:69:9;;2581:30:::1;::::0;;::::1;::::0;::::1;::::0;-1:-1:-1;2581:30:9::1;::::0;;;::::1;;::::0;::::1;:::i;:::-;-1:-1:-1::0;2581:30:9::1;::::0;;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;;;;1350:1:0;2399:219:9::0;;;;:::o;843:120::-;-1:-1:-1;;;;;939:17:9;;;;;;:10;:17;;;;;;;;;932:24;;;;;;;;;;;;;;;;;904:16;;932:24;;;939:17;932:24;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;932:24:9;;;;;;;;;;;;;;;;;;;;;;;843:120;;;:::o;1994:240:0:-;1114:7;1140:6;-1:-1:-1;;;;;1140:6:0;665:10:7;1280:23:0;1272:68;;;;-1:-1:-1;;;1272:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;2082:22:0;::::1;2074:73;;;::::0;-1:-1:-1;;;2074:73:0;;5570:2:24;2074:73:0::1;::::0;::::1;5552:21:24::0;5609:2;5589:18;;;5582:30;5648:34;5628:18;;;5621:62;-1:-1:-1;;;5699:18:24;;;5692:36;5745:19;;2074:73:0::1;5542:228:24::0;2074:73:0::1;2183:6;::::0;;2162:38:::1;::::0;-1:-1:-1;;;;;2162:38:0;;::::1;::::0;2183:6;::::1;::::0;2162:38:::1;::::0;::::1;2210:6;:17:::0;;-1:-1:-1;;;;;;2210:17:0::1;-1:-1:-1::0;;;;;2210:17:0;;;::::1;::::0;;;::::1;::::0;;1994:240::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:173:24;82:20;;-1:-1:-1;;;;;131:31:24;;121:42;;111:2;;177:1;174;167:12;111:2;63:124;;;:::o;192:375::-;243:8;253:6;307:3;300:4;292:6;288:17;284:27;274:2;;332:8;322;315:26;274:2;-1:-1:-1;362:20:24;;405:18;394:30;;391:2;;;444:8;434;427:26;391:2;488:4;480:6;476:17;464:29;;540:3;533:4;524:6;516;512:19;508:30;505:39;502:2;;;557:1;554;547:12;502:2;264:303;;;;;:::o;572:196::-;631:6;684:2;672:9;663:7;659:23;655:32;652:2;;;705:6;697;690:22;652:2;733:29;752:9;733:29;:::i;:::-;723:39;642:126;-1:-1:-1;;;642:126:24:o;773:270::-;841:6;849;902:2;890:9;881:7;877:23;873:32;870:2;;;923:6;915;908:22;870:2;951:29;970:9;951:29;:::i;:::-;941:39;;999:38;1033:2;1022:9;1018:18;999:38;:::i;:::-;989:48;;860:183;;;;;:::o;1048:264::-;1116:6;1124;1177:2;1165:9;1156:7;1152:23;1148:32;1145:2;;;1198:6;1190;1183:22;1145:2;1226:29;1245:9;1226:29;:::i;:::-;1216:39;1302:2;1287:18;;;;1274:32;;-1:-1:-1;;;1135:177:24:o;1317:747::-;1407:6;1415;1423;1431;1484:2;1472:9;1463:7;1459:23;1455:32;1452:2;;;1505:6;1497;1490:22;1452:2;1550:9;1537:23;1579:18;1620:2;1612:6;1609:14;1606:2;;;1641:6;1633;1626:22;1606:2;1685:58;1735:7;1726:6;1715:9;1711:22;1685:58;:::i;:::-;1762:8;;-1:-1:-1;1659:84:24;-1:-1:-1;1850:2:24;1835:18;;1822:32;;-1:-1:-1;1866:16:24;;;1863:2;;;1900:6;1892;1885:22;1863:2;;1944:60;1996:7;1985:8;1974:9;1970:24;1944:60;:::i;:::-;1442:622;;;;-1:-1:-1;2023:8:24;-1:-1:-1;;;;1442:622:24:o;2069:190::-;2128:6;2181:2;2169:9;2160:7;2156:23;2152:32;2149:2;;;2202:6;2194;2187:22;2149:2;-1:-1:-1;2230:23:24;;2139:120;-1:-1:-1;2139:120:24:o;2264:257::-;2305:3;2343:5;2337:12;2370:6;2365:3;2358:19;2386:63;2442:6;2435:4;2430:3;2426:14;2419:4;2412:5;2408:16;2386:63;:::i;:::-;2503:2;2482:15;-1:-1:-1;;2478:29:24;2469:39;;;;2510:4;2465:50;;2313:208;-1:-1:-1;;2313:208:24:o;2526:480::-;2766:26;2762:31;2753:6;2749:2;2745:15;2741:53;2736:3;2729:66;2711:3;2824:6;2818:13;2840:62;2895:6;2890:2;2885:3;2881:12;2874:4;2866:6;2862:17;2840:62;:::i;:::-;2961:2;2921:16;;2953:11;;;2946:27;;;;2997:2;2989:11;;2719:287;-1:-1:-1;;;2719:287:24:o;3011:466::-;3186:3;3224:6;3218:13;3240:53;3286:6;3281:3;3274:4;3266:6;3262:17;3240:53;:::i;:::-;3356:13;;3315:16;;;;3378:57;3356:13;3315:16;3412:4;3400:17;;3378:57;:::i;:::-;3451:20;;3194:283;-1:-1:-1;;;;3194:283:24:o;3969:661::-;4140:2;4192:21;;;4262:13;;4165:18;;;4284:22;;;4111:4;;4140:2;4363:15;;;;4337:2;4322:18;;;4111:4;4409:195;4423:6;4420:1;4417:13;4409:195;;;4488:13;;-1:-1:-1;;;;;4484:39:24;4472:52;;4579:15;;;;4544:12;;;;4520:1;4438:9;4409:195;;;-1:-1:-1;4621:3:24;;4120:510;-1:-1:-1;;;;;;4120:510:24:o;4635:377::-;4828:2;4817:9;4810:21;4791:4;4854:44;4894:2;4883:9;4879:18;4871:6;4854:44;:::i;:::-;4946:9;4938:6;4934:22;4929:2;4918:9;4914:18;4907:50;4974:32;4999:6;4991;4974:32;:::i;:::-;4966:40;4800:212;-1:-1:-1;;;;;4800:212:24:o;6527:356::-;6729:2;6711:21;;;6748:18;;;6741:30;6807:34;6802:2;6787:18;;6780:62;6874:2;6859:18;;6701:182::o;7581:258::-;7653:1;7663:113;7677:6;7674:1;7671:13;7663:113;;;7753:11;;;7747:18;7734:11;;;7727:39;7699:2;7692:10;7663:113;;;7794:6;7791:1;7788:13;7785:2;;;-1:-1:-1;;7829:1:24;7811:16;;7804:27;7634:205::o;7844:380::-;7923:1;7919:12;;;;7966;;;7987:2;;8041:4;8033:6;8029:17;8019:27;;7987:2;8094;8086:6;8083:14;8063:18;8060:38;8057:2;;;8140:10;8135:3;8131:20;8128:1;8121:31;8175:4;8172:1;8165:15;8203:4;8200:1;8193:15;8057:2;;7899:325;;;:::o
Swarm Source
ipfs://bb832dfbf341d571e5795e85faa4eb3ebd2d7d87f8cb807eeee5cd66e1acbaaa
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.