Polygon Sponsored slots available. Book your slot here!
Overview
POL Balance
POL Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
BobVault
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: CC0-1.0 pragma solidity 0.8.15; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./yield/YieldConnector.sol"; import "./proxy/EIP1967Admin.sol"; import "./utils/Ownable.sol"; /** * @title BobVault * @dev This contract contains logic for buying/selling BOB tokens for multiple underlying collaterals at a fixed flat rate. * Locked collateral can be seamlessly invested in arbitrary yield-generating protocols (e.g. Compound or AAVE) */ contract BobVault is EIP1967Admin, Ownable, YieldConnector { using SafeERC20 for IERC20; address public yieldAdmin; // permissioned receiver of swap fees and generated compound yields address public investAdmin; // account triggering invest of excess collateral IERC20 public immutable bobToken; mapping(address => Collateral) public collateral; uint64 internal constant MAX_FEE = 0.01 ether; // 1% struct Collateral { uint128 balance; // accounted required collateral balance uint128 buffer; // buffer of tokens that should not be invested and kept as is uint96 dust; // small non-withdrawable yield to account for possible rounding issues address yield; // address of yield-generating implementation uint128 price; // X tokens / 1 bob uint64 inFee; // fee for TOKEN->BOB buys uint64 outFee; // fee for BOB->TOKEN sells } struct Stat { uint256 total; // current balance of collateral (total == required + farmed) uint256 required; // min required balance of collateral uint256 farmed; // withdrawable collateral yield } event AddCollateral(address indexed token, uint128 price); event UpdateFees(address indexed token, uint64 inFee, uint64 outFee); event EnableYield(address indexed token, address indexed yield, uint128 buffer, uint96 dust); event UpdateYield(address indexed token, address indexed yield, uint128 buffer, uint96 dust); event DisableYield(address indexed token, address indexed yield); event Invest(address indexed token, address indexed yield, uint256 amount); event Withdraw(address indexed token, address indexed yield, uint256 amount); event Farm(address indexed token, address indexed yield, uint256 amount); event FarmExtra(address indexed token, address indexed yield); event Buy(address indexed token, address indexed user, uint256 amountIn, uint256 amountOut); event Sell(address indexed token, address indexed user, uint256 amountIn, uint256 amountOut); event Swap(address indexed inToken, address outToken, address indexed user, uint256 amountIn, uint256 amountOut); event Give(address indexed token, uint256 amount); constructor(address _bobToken) { require(Address.isContract(_bobToken), "BobVault: not a contract"); bobToken = IERC20(_bobToken); _transferOwnership(address(0)); } /** * @dev Tells if given token address belongs to one of the whitelisted collaterals. * @param _token address of the token contract. * @return true, if token is a supported collateral. */ function isCollateral(address _token) external view returns (bool) { return collateral[_token].price > 0; } /** * @dev Tells the balance-related stats for the specific collateral. * @param _token address of the token contract. * @return res balance stats struct. */ function stat(address _token) external returns (Stat memory res) { Collateral storage token = collateral[_token]; require(token.price > 0, "BobVault: unsupported collateral"); res.total = IERC20(_token).balanceOf(address(this)); res.required = token.balance; if (token.yield != address(0)) { res.total += _delegateInvestedAmount(token.yield, _token); res.required += token.dust; } res.farmed = res.total - res.required; } /** * @dev Adds a new collateral token. * Any tokens with reentrant transfers, such as an ERC777 token, MUST NOT be used as collateral. Otherwise * it could lead to inconsistent event orderings or potentially more severe issues. * Callable only by the contract owner / proxy admin. * @param _token address of added collateral token. Token can be added only once. * @param _collateral added collateral settings. */ function addCollateral(address _token, Collateral calldata _collateral) external onlyOwner { Collateral storage token = collateral[_token]; require(token.price == 0, "BobVault: already initialized collateral"); require(_collateral.price > 0, "BobVault: invalid price"); require(_collateral.inFee <= MAX_FEE, "BobVault: invalid inFee"); require(_collateral.outFee <= MAX_FEE, "BobVault: invalid outFee"); emit UpdateFees(_token, _collateral.inFee, _collateral.outFee); (token.price, token.inFee, token.outFee) = (_collateral.price, _collateral.inFee, _collateral.outFee); if (_collateral.yield != address(0)) { _enableCollateralYield(_token, _collateral.yield, _collateral.buffer, _collateral.dust); } emit AddCollateral(_token, _collateral.price); } /** * @dev Enables yield-earning on the particular collateral token. * Callable only by the contract owner / proxy admin. * In order to change yield provider for already yield-enabled tokens, * disableCollateralYield should be called first. * @param _token address of the collateral token. * @param _yield address of the yield provider contract. * @param _buffer amount of non-invested collateral. * @param _dust small amount of non-withdrawable yield. */ function enableCollateralYield(address _token, address _yield, uint128 _buffer, uint96 _dust) external onlyOwner { Collateral storage token = collateral[_token]; require(token.price > 0, "BobVault: unsupported collateral"); require(token.yield == address(0), "BobVault: yield already enabled"); _enableCollateralYield(_token, _yield, _buffer, _dust); } /** * @dev Updates yield-earning parameters on the particular collateral token. * Callable only by the contract owner / proxy admin. * @param _token address of the collateral token. * @param _buffer amount of non-invested collateral. * @param _dust small amount of non-withdrawable yield. */ function updateCollateralYield(address _token, uint128 _buffer, uint96 _dust) external onlyOwner { Collateral storage token = collateral[_token]; require(token.price > 0, "BobVault: unsupported collateral"); address yield = token.yield; require(yield != address(0), "BobVault: yield not enabled"); (token.buffer, token.dust) = (_buffer, _dust); _investExcess(_token, yield, _buffer); emit UpdateYield(_token, yield, _buffer, _dust); } /** * @dev Internal function that enables yield-earning on the particular collateral token. * Delegate-calls initialize and invest functions on the yield provider contract. * @param _token address of the collateral token. * @param _yield address of the yield provider contract. * @param _buffer amount of non-invested collateral. * @param _dust small amount of non-withdrawable yield. */ function _enableCollateralYield(address _token, address _yield, uint128 _buffer, uint96 _dust) internal { Collateral storage token = collateral[_token]; require(Address.isContract(_yield), "BobVault: yield not a contract"); (token.buffer, token.dust, token.yield) = (_buffer, _dust, _yield); _delegateInitialize(_yield, _token); _investExcess(_token, _yield, _buffer); emit EnableYield(_token, _yield, _buffer, _dust); } /** * @dev Disable yield-earning on the particular collateral token. * Callable only by the contract owner / proxy admin. * Yield can only be disabled on collaterals on which enableCollateralYield was called first. * Delegate-calls investedAmount, withdraw and exit functions on the yield provider contract. * @param _token address of the collateral token. */ function disableCollateralYield(address _token) external onlyOwner { Collateral storage token = collateral[_token]; require(token.price > 0, "BobVault: unsupported collateral"); address yield = token.yield; require(yield != address(0), "BobVault: yield not enabled"); (token.buffer, token.dust, token.yield) = (0, 0, address(0)); uint256 invested = _delegateInvestedAmount(yield, _token); _delegateWithdraw(yield, _token, invested); emit Withdraw(_token, yield, invested); _delegateExit(yield, _token); emit DisableYield(_token, yield); } /** * @dev Updates in/out fees on the particular collateral. * Callable only by the contract owner / proxy admin. * Can only be called on already whitelisted collaterals. * @param _token address of the collateral token. * @param _inFee fee for TOKEN->BOB buys (or 1 ether to pause buys). * @param _outFee fee for BOB->TOKEN sells (or 1 ether to pause sells). */ function setCollateralFees(address _token, uint64 _inFee, uint64 _outFee) external onlyOwner { Collateral storage token = collateral[_token]; require(token.price > 0, "BobVault: unsupported collateral"); require(_inFee <= MAX_FEE || _inFee == 1 ether, "BobVault: invalid inFee"); require(_outFee <= MAX_FEE || _outFee == 1 ether, "BobVault: invalid outFee"); (token.inFee, token.outFee) = (_inFee, _outFee); emit UpdateFees(_token, _inFee, _outFee); } /** * @dev Sets address of the yield receiver account. * Callable only by the contract owner / proxy admin. * Nominated address will be capable of withdrawing accumulated fees and generated yields by calling farm function. * @param _yieldAdmin new yield receiver address. */ function setYieldAdmin(address _yieldAdmin) external onlyOwner { yieldAdmin = _yieldAdmin; } /** * @dev Sets address of the invest manager. * Callable only by the contract owner / proxy admin. * Nominated address will be only capable of investing excess collateral tokens by calling invest function. * @param _investAdmin new invest manager address. */ function setInvestAdmin(address _investAdmin) external onlyOwner { investAdmin = _investAdmin; } /** * @dev Estimates amount of received tokens, when swapping some amount of inToken for outToken. * @param _inToken address of the sold token. Can be either the address of BOB token or one of whitelisted collaterals. * @param _outToken address of the bought token. Can be either the address of BOB token or one of whitelisted collaterals. * @param _inAmount amount of sold _inToken. * @return estimated amount of received _outToken. */ function getAmountOut(address _inToken, address _outToken, uint256 _inAmount) public view returns (uint256) { require(_inToken != _outToken, "BobVault: tokens should be different"); if (_outToken == address(bobToken)) { Collateral storage token = collateral[_inToken]; require(token.price > 0, "BobVault: unsupported collateral"); require(token.inFee <= MAX_FEE, "BobVault: collateral deposit suspended"); uint256 fee = _inAmount * uint256(token.inFee) / 1 ether; uint256 sellAmount = _inAmount - fee; uint256 outAmount = sellAmount * 1 ether / token.price; require(outAmount <= bobToken.balanceOf(address(this)), "BobVault: exceeds available liquidity"); return outAmount; } else if (_inToken == address(bobToken)) { Collateral storage token = collateral[_outToken]; require(token.price > 0, "BobVault: unsupported collateral"); require(token.outFee <= MAX_FEE, "BobVault: collateral withdrawal suspended"); uint256 outAmount = _inAmount * token.price / 1 ether; // collected outFee should be available for withdrawal after the swap, // so collateral liquidity is checked before subtracting the fee require(token.balance >= outAmount, "BobVault: insufficient liquidity for collateral"); outAmount -= outAmount * uint256(token.outFee) / 1 ether; return outAmount; } else { Collateral storage inToken = collateral[_inToken]; Collateral storage outToken = collateral[_outToken]; require(inToken.price > 0, "BobVault: unsupported input collateral"); require(outToken.price > 0, "BobVault: unsupported output collateral"); require(inToken.inFee <= MAX_FEE, "BobVault: collateral deposit suspended"); require(outToken.outFee <= MAX_FEE, "BobVault: collateral withdrawal suspended"); uint256 fee = _inAmount * uint256(inToken.inFee) / 1 ether; uint256 sellAmount = _inAmount - fee; uint256 bobAmount = sellAmount * 1 ether / inToken.price; uint256 outAmount = bobAmount * outToken.price / 1 ether; // collected outFee should be available for withdrawal after the swap, // so collateral liquidity is checked before subtracting the fee require(outToken.balance >= outAmount, "BobVault: insufficient liquidity for collateral"); outAmount -= outAmount * uint256(outToken.outFee) / 1 ether; return outAmount; } } /** * @dev Estimates amount of tokens that should be sold, in order to get required amount of out bought tokens, * when swapping inToken for outToken. * @param _inToken address of the sold token. Can be either the address of BOB token or one of whitelisted collaterals. * @param _outToken address of the bought token. Can be either the address of BOB token or one of whitelisted collaterals. * @param _outAmount desired amount of bought _outToken. * @return estimated amount of _inToken that should be sold. */ function getAmountIn(address _inToken, address _outToken, uint256 _outAmount) public view returns (uint256) { require(_inToken != _outToken, "BobVault: tokens should be different"); if (_outToken == address(bobToken)) { Collateral storage token = collateral[_inToken]; require(token.price > 0, "BobVault: unsupported collateral"); require(token.inFee <= MAX_FEE, "BobVault: collateral deposit suspended"); require(_outAmount <= bobToken.balanceOf(address(this)), "BobVault: exceeds available liquidity"); uint256 sellAmount = _outAmount * token.price / 1 ether; uint256 inAmount = sellAmount * 1 ether / (1 ether - uint256(token.inFee)); return inAmount; } else if (_inToken == address(bobToken)) { Collateral storage token = collateral[_outToken]; require(token.price > 0, "BobVault: unsupported collateral"); require(token.outFee <= MAX_FEE, "BobVault: collateral withdrawal suspended"); uint256 buyAmount = _outAmount * 1 ether / (1 ether - uint256(token.outFee)); // collected outFee should be available for withdrawal after the swap, // so collateral liquidity is checked before subtracting the fee require(token.balance >= buyAmount, "BobVault: insufficient liquidity for collateral"); uint256 inAmount = buyAmount * 1 ether / token.price; return inAmount; } else { Collateral storage inToken = collateral[_inToken]; Collateral storage outToken = collateral[_outToken]; require(inToken.price > 0, "BobVault: unsupported input collateral"); require(outToken.price > 0, "BobVault: unsupported output collateral"); require(inToken.inFee <= MAX_FEE, "BobVault: collateral deposit suspended"); require(outToken.outFee <= MAX_FEE, "BobVault: collateral withdrawal suspended"); uint256 buyAmount = _outAmount * 1 ether / (1 ether - uint256(outToken.outFee)); // collected outFee should be available for withdrawal after the swap, // so collateral liquidity is checked before subtracting the fee require(outToken.balance >= buyAmount, "BobVault: insufficient liquidity for collateral"); uint256 bobAmount = buyAmount * 1 ether / outToken.price; uint256 sellAmount = bobAmount * inToken.price / 1 ether; uint256 inAmount = sellAmount * 1 ether / (1 ether - uint256(inToken.inFee)); return inAmount; } } /** * @dev Buys BOB with one of the collaterals at a fixed rate. * Collateral token should be pre-approved to the vault contract. * Swap will revert, if order cannot be fully filled due to the lack of BOB tokens. * Swapped amount of collateral will be subject to relevant inFee. * @param _token address of the sold collateral token. * @param _amount amount of sold collateral. * @return amount of received _outToken, i.e. getAmountOut(_token, BOB, _amount). */ function buy(address _token, uint256 _amount) external returns (uint256) { Collateral storage token = collateral[_token]; require(token.price > 0, "BobVault: unsupported collateral"); require(token.inFee <= MAX_FEE, "BobVault: collateral deposit suspended"); IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount); uint256 fee = _amount * uint256(token.inFee) / 1 ether; uint256 sellAmount = _amount - fee; uint256 buyAmount = sellAmount * 1 ether / token.price; unchecked { require(token.balance + sellAmount <= type(uint128).max, "BobVault: amount too large"); token.balance += uint128(sellAmount); } bobToken.transfer(msg.sender, buyAmount); emit Buy(_token, msg.sender, _amount, buyAmount); return buyAmount; } /** * @dev Sells BOB for one of the collaterals at a fixed rate. * BOB token should be pre-approved to the vault contract. * Swap will revert, if order cannot be fully filled due to the lack of particular collateral. * Swapped amount of collateral will be subject to relevant outFee. * @param _token address of the received collateral token. * @param _amount amount of sold BOB tokens. * @return amount of received _outToken, i.e. getAmountOut(BOB, _token, _amount). */ function sell(address _token, uint256 _amount) external returns (uint256) { Collateral storage token = collateral[_token]; require(token.price > 0, "BobVault: unsupported collateral"); require(token.outFee <= MAX_FEE, "BobVault: collateral withdrawal suspended"); bobToken.transferFrom(msg.sender, address(this), _amount); uint256 buyAmount = _amount * token.price / 1 ether; // collected outFee should be available for withdrawal after the swap, // so collateral liquidity is checked before subtracting the fee require(token.balance >= buyAmount, "BobVault: insufficient liquidity for collateral"); unchecked { token.balance -= uint128(buyAmount); } buyAmount -= buyAmount * uint256(token.outFee) / 1 ether; _transferOut(_token, msg.sender, buyAmount); emit Sell(_token, msg.sender, _amount, buyAmount); return buyAmount; } /** * @dev Buys one collateral with another collateral by virtually routing swap through BOB token at a fixed rate. * Collateral token should be pre-approved to the vault contract. * Identical to sequence of buy+sell calls, * with the exception that swap does not require presence of the BOB liquidity and has a much lower gas usage. * Swap will revert, if order cannot be fully filled due to the lack of particular collateral. * Swapped amount of collateral will be subject to relevant inFee and outFee. * @param _inToken address of the sold collateral token. * @param _outToken address of the bought collateral token. * @param _amount amount of sold collateral. * @return amount of received _outToken, i.e. getAmountOut(_inToken, _outToken, _amount). */ function swap(address _inToken, address _outToken, uint256 _amount) external returns (uint256) { Collateral storage inToken = collateral[_inToken]; Collateral storage outToken = collateral[_outToken]; require(_inToken != _outToken, "BobVault: tokens should be different"); require(inToken.price > 0, "BobVault: unsupported input collateral"); require(outToken.price > 0, "BobVault: unsupported output collateral"); require(inToken.inFee <= MAX_FEE, "BobVault: collateral deposit suspended"); require(outToken.outFee <= MAX_FEE, "BobVault: collateral withdrawal suspended"); IERC20(_inToken).safeTransferFrom(msg.sender, address(this), _amount); // buy virtual bob uint256 fee = _amount * uint256(inToken.inFee) / 1 ether; uint256 sellAmount = _amount - fee; unchecked { require(inToken.balance + sellAmount <= type(uint128).max, "BobVault: amount too large"); inToken.balance += uint128(sellAmount); } uint256 bobAmount = sellAmount * 1 ether / inToken.price; // sell virtual bob uint256 buyAmount = bobAmount * outToken.price / 1 ether; // collected outFee should be available for withdrawal after the swap, // so collateral liquidity is checked before subtracting the fee require(outToken.balance >= buyAmount, "BobVault: insufficient liquidity for collateral"); unchecked { outToken.balance -= uint128(buyAmount); } buyAmount -= buyAmount * uint256(outToken.outFee) / 1 ether; _transferOut(_outToken, msg.sender, buyAmount); emit Swap(_inToken, _outToken, msg.sender, _amount, buyAmount); return buyAmount; } /** * @dev Invests excess tokens into the yield provider. * Callable only by the contract owner / proxy admin / invest admin. * @param _token address of collateral to invest. */ function invest(address _token) external { require(msg.sender == investAdmin || _isOwner(), "BobVault: not authorized"); Collateral storage token = collateral[_token]; require(token.price > 0, "BobVault: unsupported collateral"); _investExcess(_token, token.yield, token.buffer); } /** * @dev Internal function for investing excess tokens into the yield provider. * Delegate-calls invest function on the yield provider contract. * @param _token address of collateral to invest. */ function _investExcess(address _token, address _yield, uint256 _buffer) internal { uint256 balance = IERC20(_token).balanceOf(address(this)); if (balance > _buffer) { uint256 value = balance - _buffer; _delegateInvest(_yield, _token, value); emit Invest(_token, _yield, value); } } /** * @dev Collects accumulated fees and generated yield for the specific collateral. * Callable only by the contract owner / proxy admin / yield admin. * @param _token address of collateral to collect fess / interest for. */ function farm(address _token) external returns (uint256) { require(msg.sender == yieldAdmin || _isOwner(), "BobVault: not authorized"); Collateral storage token = collateral[_token]; require(token.price > 0, "BobVault: unsupported collateral"); uint256 currentBalance = IERC20(_token).balanceOf(address(this)); uint256 requiredBalance = token.balance; if (token.yield != address(0)) { currentBalance += _delegateInvestedAmount(token.yield, _token); requiredBalance += token.dust; } if (requiredBalance >= currentBalance) { return 0; } uint256 value = currentBalance - requiredBalance; _transferOut(_token, msg.sender, value); emit Farm(_token, token.yield, value); return value; } /** * @dev Collects extra rewards from the specific yield provider (e.g. COMP tokens). * Callable only by the contract owner / proxy admin / yield admin. * @param _token address of collateral to collect rewards for. * @param _data arbitrary extra data required for rewards collection. */ function farmExtra(address _token, bytes calldata _data) external returns (bytes memory returnData) { require(msg.sender == yieldAdmin || _isOwner(), "BobVault: not authorized"); Collateral memory token = collateral[_token]; require(token.price > 0, "BobVault: unsupported collateral"); returnData = _delegateFarmExtra(token.yield, _token, msg.sender, _data); emit FarmExtra(_token, token.yield); } /** * @dev Top up balance of the particular collateral. * Can be used when migrating liquidity from other sources (e.g. from Uniswap). * @param _token address of collateral to top up. * @param _amount amount of collateral to add. */ function give(address _token, uint256 _amount) external { Collateral storage token = collateral[_token]; require(token.price > 0, "BobVault: unsupported collateral"); IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount); unchecked { require(token.balance + _amount <= type(uint128).max, "BobVault: amount too large"); token.balance += uint128(_amount); } emit Give(_token, _amount); } /** * @dev Withdraws BOB liquidity. * Can be used when migrating BOB liquidity into other pools. (e.g. to a different BobVault contract). * Will withdraw at most _value tokens, but no more than the current available balance. * @param _to address of BOB tokens receiver. * @param _value max amount of BOB tokens to withdraw. */ function reclaim(address _to, uint256 _value) external onlyOwner { uint256 balance = bobToken.balanceOf(address(this)); uint256 value = balance > _value ? _value : balance; if (value > 0) { bobToken.transfer(_to, value); } } /** * @dev Internal function for doing collateral payouts. * Delegate-calls investedAmount and withdraw functions on the yield provider contract. * Seamlessly withdraws the necessary amount of invested liquidity, when needed. * @param _token address of withdrawn collateral token. * @param _to address of withdrawn collateral receiver. * @param _value amount of collateral tokens to withdraw. */ function _transferOut(address _token, address _to, uint256 _value) internal { Collateral storage token = collateral[_token]; uint256 balance = IERC20(_token).balanceOf(address(this)); if (_value > balance) { address yield = token.yield; require(yield != address(0), "BobVault: yield not enabled"); uint256 invested = _delegateInvestedAmount(yield, _token); uint256 withdrawValue = token.buffer + _value - balance; if (invested < withdrawValue) { withdrawValue = invested; } _delegateWithdraw(token.yield, _token, withdrawValue); emit Withdraw(_token, yield, withdrawValue); } IERC20(_token).safeTransfer(_to, _value); } /** * @dev Tells if caller is the contract owner. * Gives ownership rights to the proxy admin as well. * @return true, if caller is the contract owner or proxy admin. */ function _isOwner() internal view override returns (bool) { return super._isOwner() || _admin() == _msgSender(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.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)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: CC0-1.0 pragma solidity 0.8.15; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IYieldImplementation { function initialize(address _token) external; function exit(address _token) external; function invest(address _token, uint256 _amount) external; function withdraw(address _token, uint256 _amount) external; function farmExtra(address _token, address _to, bytes calldata _data) external returns (bytes memory); function investedAmount(address _token) external returns (uint256); }
// SPDX-License-Identifier: CC0-1.0 pragma solidity 0.8.15; /** * @title EIP1967Admin * @dev Upgradeable proxy pattern implementation according to minimalistic EIP1967. */ contract EIP1967Admin { // EIP 1967 // bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1) uint256 internal constant EIP1967_ADMIN_STORAGE = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; modifier onlyAdmin() { require(msg.sender == _admin(), "EIP1967Admin: not an admin"); _; } function _admin() internal view returns (address res) { assembly { res := sload(EIP1967_ADMIN_STORAGE) } } }
// SPDX-License-Identifier: CC0-1.0 pragma solidity 0.8.15; import "@openzeppelin/contracts/access/Ownable.sol" as OZOwnable; /** * @title Ownable */ contract Ownable is OZOwnable.Ownable { /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view override { require(_isOwner(), "Ownable: caller is not the owner"); } /** * @dev Tells if caller is the contract owner. * @return true, if caller is the contract owner. */ function _isOwner() internal view virtual returns (bool) { return owner() == _msgSender(); } }
// SPDX-License-Identifier: CC0-1.0 pragma solidity 0.8.15; import "@openzeppelin/contracts/utils/Address.sol"; import "../interfaces/IYieldImplementation.sol"; /** * @title YieldConnector */ contract YieldConnector { function _delegateInitialize(address _impl, address _token) internal { _delegate(_impl, abi.encodeWithSelector(IYieldImplementation.initialize.selector, _token)); } function _delegateExit(address _impl, address _token) internal { _delegate(_impl, abi.encodeWithSelector(IYieldImplementation.exit.selector, _token)); } function _delegateInvest(address _impl, address _token, uint256 _amount) internal { _delegate(_impl, abi.encodeWithSelector(IYieldImplementation.invest.selector, _token, _amount)); } function _delegateWithdraw(address _impl, address _token, uint256 _amount) internal { _delegate(_impl, abi.encodeWithSelector(IYieldImplementation.withdraw.selector, _token, _amount)); } function _delegateInvestedAmount(address _impl, address _token) internal returns (uint256) { bytes memory data = _delegate(_impl, abi.encodeWithSelector(IYieldImplementation.investedAmount.selector, _token)); return abi.decode(data, (uint256)); } function _delegateFarmExtra( address _impl, address _token, address _to, bytes calldata _data ) internal returns (bytes memory) { return _delegate(_impl, abi.encodeWithSelector(IYieldImplementation.farmExtra.selector, _token, _to, _data)); } function _delegate(address _impl, bytes memory _data) private returns (bytes memory) { (bool status, bytes memory data) = _impl.delegatecall(_data); require(status, "YieldConnector: delegatecall failed"); return data; } }
{ "remappings": [ "@gnosis/=lib/@gnosis/", "@gnosis/auction/=lib/@gnosis/auction/contracts/", "@openzeppelin/=lib/@openzeppelin/contracts/", "@openzeppelin/contracts/=lib/@openzeppelin/contracts/contracts/", "@uniswap/=lib/@uniswap/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_bobToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint128","name":"price","type":"uint128"}],"name":"AddCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"Buy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"yield","type":"address"}],"name":"DisableYield","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"yield","type":"address"},{"indexed":false,"internalType":"uint128","name":"buffer","type":"uint128"},{"indexed":false,"internalType":"uint96","name":"dust","type":"uint96"}],"name":"EnableYield","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"yield","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Farm","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"yield","type":"address"}],"name":"FarmExtra","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Give","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"yield","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Invest","type":"event"},{"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":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"Sell","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"inToken","type":"address"},{"indexed":false,"internalType":"address","name":"outToken","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint64","name":"inFee","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"outFee","type":"uint64"}],"name":"UpdateFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"yield","type":"address"},{"indexed":false,"internalType":"uint128","name":"buffer","type":"uint128"},{"indexed":false,"internalType":"uint96","name":"dust","type":"uint96"}],"name":"UpdateYield","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"yield","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"components":[{"internalType":"uint128","name":"balance","type":"uint128"},{"internalType":"uint128","name":"buffer","type":"uint128"},{"internalType":"uint96","name":"dust","type":"uint96"},{"internalType":"address","name":"yield","type":"address"},{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint64","name":"inFee","type":"uint64"},{"internalType":"uint64","name":"outFee","type":"uint64"}],"internalType":"struct BobVault.Collateral","name":"_collateral","type":"tuple"}],"name":"addCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bobToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"buy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"collateral","outputs":[{"internalType":"uint128","name":"balance","type":"uint128"},{"internalType":"uint128","name":"buffer","type":"uint128"},{"internalType":"uint96","name":"dust","type":"uint96"},{"internalType":"address","name":"yield","type":"address"},{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint64","name":"inFee","type":"uint64"},{"internalType":"uint64","name":"outFee","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"disableCollateralYield","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_yield","type":"address"},{"internalType":"uint128","name":"_buffer","type":"uint128"},{"internalType":"uint96","name":"_dust","type":"uint96"}],"name":"enableCollateralYield","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"farm","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"farmExtra","outputs":[{"internalType":"bytes","name":"returnData","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_inToken","type":"address"},{"internalType":"address","name":"_outToken","type":"address"},{"internalType":"uint256","name":"_outAmount","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_inToken","type":"address"},{"internalType":"address","name":"_outToken","type":"address"},{"internalType":"uint256","name":"_inAmount","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"give","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"invest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"investAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"isCollateral","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"reclaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"sell","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint64","name":"_inFee","type":"uint64"},{"internalType":"uint64","name":"_outFee","type":"uint64"}],"name":"setCollateralFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_investAdmin","type":"address"}],"name":"setInvestAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_yieldAdmin","type":"address"}],"name":"setYieldAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"stat","outputs":[{"components":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"},{"internalType":"uint256","name":"farmed","type":"uint256"}],"internalType":"struct BobVault.Stat","name":"res","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_inToken","type":"address"},{"internalType":"address","name":"_outToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"swap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint128","name":"_buffer","type":"uint128"},{"internalType":"uint96","name":"_dust","type":"uint96"}],"name":"updateCollateralYield","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"yieldAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b5060405162003a4138038062003a41833981016040819052620000349162000125565b6200003f33620000c6565b62000055816200011660201b620027e31760201c565b620000a65760405162461bcd60e51b815260206004820152601860248201527f426f625661756c743a206e6f74206120636f6e74726163740000000000000000604482015260640160405180910390fd5b6001600160a01b038116608052620000bf6000620000c6565b5062000157565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03163b151590565b6000602082840312156200013857600080fd5b81516001600160a01b03811681146200015057600080fd5b9392505050565b608051613888620001b9600039600081816102cc015281816108a2015281816109e301528181610a8201528181610e2101528181610eeb01528181610ff7015281816113ea015281816115a90152818161165d0152611b9a01526138886000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80638da5cb5b116100de578063d2794f6311610097578063df791e5011610071578063df791e5014610499578063f00388f7146104ac578063f2fde38b146104bf578063fa9dbe27146104d257600080fd5b8063d2794f6314610460578063d51c049714610473578063d66e99771461048657600080fd5b80638da5cb5b14610301578063a32f386c14610312578063a5fdc5de14610325578063a909091714610405578063b124bce514610418578063cce7ec131461044d57600080fd5b80634aa066521161014b5780636c197ff5116101255780636c197ff5146102ac578063715018a6146102bf5780638a6e0249146102c75780638bd317eb146102ee57600080fd5b80634aa066521461024d57806353b609b51461026e578063676011551461028157600080fd5b806303f9c793146101935780630ee21e54146101a85780630fcff772146101f457806318a467aa1461021457806320d22739146102275780633dd0d01b1461023a575b600080fd5b6101a66101a1366004613146565b6104e5565b005b6101df6101b6366004613146565b6001600160a01b03166000908152600360205260409020600201546001600160801b0316151590565b60405190151581526020015b60405180910390f35b610207610202366004613161565b6105a0565b6040516101eb919061323b565b6101a6610222366004613146565b6106f1565b6101a661023536600461327c565b61071b565b6101a6610248366004613146565b610843565b61026061025b3660046132bf565b61086d565b6040519081526020016101eb565b61026061027c3660046132bf565b610dec565b600154610294906001600160a01b031681565b6040516001600160a01b0390911681526020016101eb565b6102606102ba3660046132fb565b61134a565b6101a6611575565b6102947f000000000000000000000000000000000000000000000000000000000000000081565b6101a66102fc3660046132fb565b611589565b6000546001600160a01b0316610294565b600254610294906001600160a01b031681565b6103a0610333366004613146565b6003602052600090815260409020805460018201546002909201546001600160801b0380831693600160801b938490048216936001600160601b03821693600160601b9092046001600160a01b0316928216919081046001600160401b0390811691600160c01b90041687565b604080516001600160801b03988916815296881660208801526001600160601b03909516948601949094526001600160a01b0390921660608501529390931660808301526001600160401b0392831660a08301529190911660c082015260e0016101eb565b610260610413366004613146565b6116d2565b61042b610426366004613146565b6118b3565b60408051825181526020808401519082015291810151908201526060016101eb565b61026061045b3660046132fb565b611a20565b6101a661046e36600461333c565b611c58565b6101a6610481366004613146565b611e1b565b6101a6610494366004613376565b611f61565b6102606104a73660046132bf565b6122d1565b6101a66104ba3660046132fb565b6125d4565b6101a66104cd366004613146565b6126b2565b6101a66104e03660046133b6565b61272b565b6002546001600160a01b031633148061050157506105016127f2565b6105265760405162461bcd60e51b815260040161051d9061340a565b60405180910390fd5b6001600160a01b038116600090815260036020526040902060028101546001600160801b03166105685760405162461bcd60e51b815260040161051d90613441565b6001810154815461059c918491600160601b9091046001600160a01b031690600160801b90046001600160801b0316612837565b5050565b6001546060906001600160a01b03163314806105bf57506105bf6127f2565b6105db5760405162461bcd60e51b815260040161051d9061340a565b6001600160a01b03848116600090815260036020908152604091829020825160e08101845281546001600160801b038082168352600160801b9182900481169483019490945260018301546001600160601b03811695830195909552600160601b909404909416606085015260020154908116608084018190529181046001600160401b0390811660a0850152600160c01b9091041660c08301526106925760405162461bcd60e51b815260040161051d90613441565b6106a381606001518633878761290a565b915080606001516001600160a01b0316856001600160a01b03167f388451cdba6e32008ba46b380b1f61d7b47e76bd81e07f41eba9146612d436f360405160405180910390a3509392505050565b6106f9612970565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b610723612970565b6001600160a01b038316600090815260036020526040902060028101546001600160801b03166107655760405162461bcd60e51b815260040161051d90613441565b6001810154600160601b90046001600160a01b0316806107975760405162461bcd60e51b815260040161051d90613476565b6001820180546bffffffffffffffffffffffff19166001600160601b03851617905581546001600160801b03908116600160801b9186169182021783556107e19086908390612837565b604080516001600160801b03861681526001600160601b03851660208201526001600160a01b0380841692908816917f97e7f65b045b61d192fa31c300d58a2d1f7423de3ff84b488956514d89e2897691015b60405180910390a35050505050565b61084b612970565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000826001600160a01b0316846001600160a01b0316036108a05760405162461bcd60e51b815260040161051d906134ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603610a80576001600160a01b038416600090815260036020526040902060028101546001600160801b031661091b5760405162461bcd60e51b815260040161051d90613441565b6002810154662386f26fc10000600160801b9091046001600160401b031611156109575760405162461bcd60e51b815260040161051d906134f1565b6002810154600090670de0b6b3a76400009061098390600160801b90046001600160401b03168661354d565b61098d919061356c565b9050600061099b828661358e565b60028401549091506000906001600160801b03166109c183670de0b6b3a764000061354d565b6109cb919061356c565b6040516370a0823160e01b81523060048201529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610a32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5691906135a5565b811115610a755760405162461bcd60e51b815260040161051d906135be565b9350610de592505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031603610bda576001600160a01b038316600090815260036020526040902060028101546001600160801b0316610afb5760405162461bcd60e51b815260040161051d90613441565b6002810154662386f26fc10000600160c01b9091046001600160401b03161115610b375760405162461bcd60e51b815260040161051d90613603565b6002810154600090670de0b6b3a764000090610b5c906001600160801b03168661354d565b610b66919061356c565b82549091506001600160801b0316811115610b935760405162461bcd60e51b815260040161051d9061364c565b6002820154670de0b6b3a764000090610bbc90600160c01b90046001600160401b03168361354d565b610bc6919061356c565b610bd0908261358e565b9250610de5915050565b6001600160a01b038085166000908152600360205260408082209286168252902060028201546001600160801b0316610c255760405162461bcd60e51b815260040161051d9061369b565b60028101546001600160801b0316610c4f5760405162461bcd60e51b815260040161051d906136e1565b6002820154662386f26fc10000600160801b9091046001600160401b03161115610c8b5760405162461bcd60e51b815260040161051d906134f1565b6002810154662386f26fc10000600160c01b9091046001600160401b03161115610cc75760405162461bcd60e51b815260040161051d90613603565b6002820154600090670de0b6b3a764000090610cf390600160801b90046001600160401b03168761354d565b610cfd919061356c565b90506000610d0b828761358e565b60028501549091506000906001600160801b0316610d3183670de0b6b3a764000061354d565b610d3b919061356c565b6002850154909150600090670de0b6b3a764000090610d63906001600160801b03168461354d565b610d6d919061356c565b85549091506001600160801b0316811115610d9a5760405162461bcd60e51b815260040161051d9061364c565b6002850154670de0b6b3a764000090610dc390600160c01b90046001600160401b03168361354d565b610dcd919061356c565b610dd7908261358e565b9650610de595505050505050565b9392505050565b6000826001600160a01b0316846001600160a01b031603610e1f5760405162461bcd60e51b815260040161051d906134ad565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603610ff5576001600160a01b038416600090815260036020526040902060028101546001600160801b0316610e9a5760405162461bcd60e51b815260040161051d90613441565b6002810154662386f26fc10000600160801b9091046001600160401b03161115610ed65760405162461bcd60e51b815260040161051d906134f1565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5e91906135a5565b831115610f7d5760405162461bcd60e51b815260040161051d906135be565b6002810154600090670de0b6b3a764000090610fa2906001600160801b03168661354d565b610fac919061356c565b6002830154909150600090610fd990600160801b90046001600160401b0316670de0b6b3a764000061358e565b610feb83670de0b6b3a764000061354d565b610a75919061356c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031603611142576001600160a01b038316600090815260036020526040902060028101546001600160801b03166110705760405162461bcd60e51b815260040161051d90613441565b6002810154662386f26fc10000600160c01b9091046001600160401b031611156110ac5760405162461bcd60e51b815260040161051d90613603565b60028101546000906110d690600160c01b90046001600160401b0316670de0b6b3a764000061358e565b6110e885670de0b6b3a764000061354d565b6110f2919061356c565b82549091506001600160801b031681111561111f5760405162461bcd60e51b815260040161051d9061364c565b60028201546000906001600160801b0316610feb83670de0b6b3a764000061354d565b6001600160a01b038085166000908152600360205260408082209286168252902060028201546001600160801b031661118d5760405162461bcd60e51b815260040161051d9061369b565b60028101546001600160801b03166111b75760405162461bcd60e51b815260040161051d906136e1565b6002820154662386f26fc10000600160801b9091046001600160401b031611156111f35760405162461bcd60e51b815260040161051d906134f1565b6002810154662386f26fc10000600160c01b9091046001600160401b0316111561122f5760405162461bcd60e51b815260040161051d90613603565b600281015460009061125990600160c01b90046001600160401b0316670de0b6b3a764000061358e565b61126b86670de0b6b3a764000061354d565b611275919061356c565b82549091506001600160801b03168111156112a25760405162461bcd60e51b815260040161051d9061364c565b60028201546000906001600160801b03166112c583670de0b6b3a764000061354d565b6112cf919061356c565b6002850154909150600090670de0b6b3a7640000906112f7906001600160801b03168461354d565b611301919061356c565b600286015490915060009061132e90600160801b90046001600160401b0316670de0b6b3a764000061358e565b61134083670de0b6b3a764000061354d565b610dd7919061356c565b6001600160a01b038216600090815260036020526040812060028101546001600160801b031661138c5760405162461bcd60e51b815260040161051d90613441565b6002810154662386f26fc10000600160c01b9091046001600160401b031611156113c85760405162461bcd60e51b815260040161051d90613603565b6040516323b872dd60e01b8152336004820152306024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af115801561143b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145f9190613728565b506002810154600090670de0b6b3a764000090611485906001600160801b03168661354d565b61148f919061356c565b82549091506001600160801b03168111156114bc5760405162461bcd60e51b815260040161051d9061364c565b81546001600160801b03808216839003166001600160801b03199091161782556002820154670de0b6b3a764000090611506906001600160401b03600160c01b909104168361354d565b611510919061356c565b61151a908261358e565b90506115278533836129c4565b604080518581526020810183905233916001600160a01b038816917fa082022e93cfcd9f1da5f9236718053910f7e840da080c789c7845698dc032ff910160405180910390a3949350505050565b61157d612970565b6115876000612b45565b565b611591612970565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156115f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161c91906135a5565b9050600082821161162d578161162f565b825b905080156116cc5760405163a9059cbb60e01b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af11580156116a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ca9190613728565b505b50505050565b6001546000906001600160a01b03163314806116f157506116f16127f2565b61170d5760405162461bcd60e51b815260040161051d9061340a565b6001600160a01b038216600090815260036020526040902060028101546001600160801b031661174f5760405162461bcd60e51b815260040161051d90613441565b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015611796573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117ba91906135a5565b825460018401549192506001600160801b031690600160601b90046001600160a01b03161561182a57600183015461180290600160601b90046001600160a01b031686612b95565b61180c908361374a565b6001840154909250611827906001600160601b03168261374a565b90505b81811061183c57506000949350505050565b6000611848828461358e565b90506118558633836129c4565b60018401546040516001600160a01b03600160601b9092048216918816907f22357843602b631ef738ef8439659fbccae0f50c9f1a17abcedfafd2f785a0d6906118a29085815260200190565b60405180910390a395945050505050565b6118d760405180606001604052806000815260200160008152602001600081525090565b6001600160a01b038216600090815260036020526040902060028101546001600160801b03166119195760405162461bcd60e51b815260040161051d90613441565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa15801561195d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198191906135a5565b825280546001600160801b031660208301526001810154600160601b90046001600160a01b031615611a045760018101546119cc90600160601b90046001600160a01b031684612b95565b825183906119db90839061374a565b90525060018101546020830180516001600160601b0390921691611a0090839061374a565b9052505b60208201518251611a15919061358e565b604083015250919050565b6001600160a01b038216600090815260036020526040812060028101546001600160801b0316611a625760405162461bcd60e51b815260040161051d90613441565b6002810154662386f26fc10000600160801b9091046001600160401b03161115611a9e5760405162461bcd60e51b815260040161051d906134f1565b611ab36001600160a01b038516333086612be1565b6002810154600090670de0b6b3a764000090611adf90600160801b90046001600160401b03168661354d565b611ae9919061356c565b90506000611af7828661358e565b60028401549091506000906001600160801b0316611b1d83670de0b6b3a764000061354d565b611b27919061356c565b84549091506001600160801b0390811683011115611b575760405162461bcd60e51b815260040161051d90613762565b83546001600160801b038082168401166001600160801b031990911617845560405163a9059cbb60e01b8152336004820152602481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015611be3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c079190613728565b50604080518781526020810183905233916001600160a01b038a16917f89f5adc174562e07c9c9b1cae7109bbecb21cf9d1b2847e550042b8653c54a0e910160405180910390a39695505050505050565b611c60612970565b6001600160a01b038316600090815260036020526040902060028101546001600160801b0316611ca25760405162461bcd60e51b815260040161051d90613441565b662386f26fc100006001600160401b038416111580611cd15750826001600160401b0316670de0b6b3a7640000145b611d175760405162461bcd60e51b8152602060048201526017602482015276426f625661756c743a20696e76616c696420696e46656560481b604482015260640161051d565b662386f26fc100006001600160401b038316111580611d465750816001600160401b0316670de0b6b3a7640000145b611d8d5760405162461bcd60e51b8152602060048201526018602482015277426f625661756c743a20696e76616c6964206f757446656560401b604482015260640161051d565b6002810180546001600160801b0316600160c01b6001600160401b0385811691820267ffffffffffffffff60801b191692909217600160801b928716928302179092556040805191825260208201929092526001600160a01b038616917fbacc19961151cbf3edcf4cf8653aa6017430dbe14fdc333f4e2a78229c47448a910160405180910390a250505050565b611e23612970565b6001600160a01b038116600090815260036020526040902060028101546001600160801b0316611e655760405162461bcd60e51b815260040161051d90613441565b6001810154600160601b90046001600160a01b031680611e975760405162461bcd60e51b815260040161051d90613476565b60006001830181905582546001600160801b03168355611eb78285612b95565b9050611ec4828583612c4c565b816001600160a01b0316846001600160a01b03167f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb83604051611f0991815260200190565b60405180910390a3611f1b8285612c7c565b816001600160a01b0316846001600160a01b03167f2db210ad679becb80ef14e8aad6c235b8d62bb0269252792723a6887042a60a360405160405180910390a350505050565b611f69612970565b6001600160a01b038216600090815260036020526040902060028101546001600160801b031615611fed5760405162461bcd60e51b815260206004820152602860248201527f426f625661756c743a20616c726561647920696e697469616c697a656420636f6044820152671b1b185d195c985b60c21b606482015260840161051d565b6000611fff60a0840160808501613799565b6001600160801b0316116120555760405162461bcd60e51b815260206004820152601760248201527f426f625661756c743a20696e76616c6964207072696365000000000000000000604482015260640161051d565b662386f26fc1000061206d60c0840160a085016137b4565b6001600160401b031611156120be5760405162461bcd60e51b8152602060048201526017602482015276426f625661756c743a20696e76616c696420696e46656560481b604482015260640161051d565b662386f26fc100006120d660e0840160c085016137b4565b6001600160401b031611156121285760405162461bcd60e51b8152602060048201526018602482015277426f625661756c743a20696e76616c6964206f757446656560401b604482015260640161051d565b6001600160a01b0383167fbacc19961151cbf3edcf4cf8653aa6017430dbe14fdc333f4e2a78229c47448a61216360c0850160a086016137b4565b61217360e0860160c087016137b4565b604080516001600160401b0393841681529290911660208301520160405180910390a26121a660a0830160808401613799565b6121b660c0840160a085016137b4565b6121c660e0850160c086016137b4565b6002840180546001600160801b03908116600160c01b6001600160401b039485160267ffffffffffffffff60801b191617600160801b9490931693909302919091176001600160801b03191692909116919091179055600061222e6080840160608501613146565b6001600160a01b03161461227557612275836122506080850160608601613146565b6122606040860160208701613799565b61227060608701604088016137cf565b612caa565b6001600160a01b0383167f72ef4b402b9a2c78796038c5ccfe4a0a6dda91238fdcdbf1dc7263b07ab5512c6122b060a0850160808601613799565b6040516001600160801b0390911681526020015b60405180910390a2505050565b6001600160a01b03808416600081815260036020526040808220938616808352908220919392036123145760405162461bcd60e51b815260040161051d906134ad565b60028201546001600160801b031661233e5760405162461bcd60e51b815260040161051d9061369b565b60028101546001600160801b03166123685760405162461bcd60e51b815260040161051d906136e1565b6002820154662386f26fc10000600160801b9091046001600160401b031611156123a45760405162461bcd60e51b815260040161051d906134f1565b6002810154662386f26fc10000600160c01b9091046001600160401b031611156123e05760405162461bcd60e51b815260040161051d90613603565b6123f56001600160a01b038716333087612be1565b6002820154600090670de0b6b3a76400009061242190600160801b90046001600160401b03168761354d565b61242b919061356c565b90506000612439828761358e565b84549091506001600160801b03908116820111156124695760405162461bcd60e51b815260040161051d90613762565b83546001600160801b031981166001600160801b03918216830182161785556002850154600091166124a383670de0b6b3a764000061354d565b6124ad919061356c565b6002850154909150600090670de0b6b3a7640000906124d5906001600160801b03168461354d565b6124df919061356c565b85549091506001600160801b031681111561250c5760405162461bcd60e51b815260040161051d9061364c565b84546001600160801b03808216839003166001600160801b03199091161785556002850154670de0b6b3a764000090612556906001600160401b03600160c01b909104168361354d565b612560919061356c565b61256a908261358e565b90506125778933836129c4565b604080516001600160a01b038b81168252602082018b905291810183905233918c16907fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e460629060600160405180910390a39998505050505050505050565b6001600160a01b038216600090815260036020526040902060028101546001600160801b03166126165760405162461bcd60e51b815260040161051d90613441565b61262b6001600160a01b038416333085612be1565b80546001600160801b03908116830111156126585760405162461bcd60e51b815260040161051d90613762565b80546001600160801b038082168401166001600160801b03199091161781556040518281526001600160a01b038416907fa287a305d884484886886da5686f3b9d8d30c3f3ebedd3b5fa6103ae30bcc011906020016122c4565b6126ba612970565b6001600160a01b03811661271f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161051d565b61272881612b45565b50565b612733612970565b6001600160a01b038416600090815260036020526040902060028101546001600160801b03166127755760405162461bcd60e51b815260040161051d90613441565b6001810154600160601b90046001600160a01b0316156127d75760405162461bcd60e51b815260206004820152601f60248201527f426f625661756c743a207969656c6420616c726561647920656e61626c656400604482015260640161051d565b6116ca85858585612caa565b6001600160a01b03163b151590565b60006127fc612ddd565b8061283257507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035433905b6001600160a01b0316145b905090565b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a291906135a5565b9050818111156116cc5760006128b8838361358e565b90506128c5848683612df1565b836001600160a01b0316856001600160a01b03167f0657e0c8fff72ae811b8683a3411c30ebb5098754ec5e814687711e97cbd6db28360405161083491815260200190565b60606129668663d594930f60e01b8787878760405160240161292f94939291906137ea565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612e21565b9695505050505050565b6129786127f2565b6115875760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161051d565b6001600160a01b03831660008181526003602052604080822090516370a0823160e01b81523060048201529092906370a0823190602401602060405180830381865afa158015612a18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a3c91906135a5565b905080831115612b31576001820154600160601b90046001600160a01b031680612a785760405162461bcd60e51b815260040161051d90613476565b6000612a848288612b95565b84549091506000908490612aa9908890600160801b90046001600160801b031661374a565b612ab3919061358e565b905080821015612ac05750805b6001850154612ae090600160601b90046001600160a01b03168983612c4c565b826001600160a01b0316886001600160a01b03167f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb83604051612b2591815260200190565b60405180910390a35050505b6116ca6001600160a01b0386168585612edc565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b03821660248201526000908190612bc39085906333fddd1160e21b9060440161292f565b905080806020019051810190612bd991906135a5565b949350505050565b6040516001600160a01b03808516602483015283166044820152606481018290526116cc9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612f0c565b6040516001600160a01b0383166024820152604481018290526116cc90849063f3fef3a360e01b9060640161292f565b6040516001600160a01b0382166024820152612ca590839063b42652e960e01b9060440161292f565b505050565b6001600160a01b0384166000908152600360205260409020612cd5846001600160a01b03163b151590565b612d215760405162461bcd60e51b815260206004820152601e60248201527f426f625661756c743a207969656c64206e6f74206120636f6e74726163740000604482015260640161051d565b6001600160601b0382166001600160a01b038516600160601b026bffffffffffffffffffffffff191617600182015580546001600160801b03808516600160801b029116178155612d728486612fde565b612d868585856001600160801b0316612837565b604080516001600160801b03851681526001600160601b03841660208201526001600160a01b0380871692908816917f708019cb44b26fc7e782dfbd91c4961ce197e42bbd62305799e2b50d3e8ff4fd9101610834565b6000805433906001600160a01b0316612827565b6040516001600160a01b0383166024820152604481018290526116cc908490635cdc612360e11b9060640161292f565b6060600080846001600160a01b031684604051612e3e9190613836565b600060405180830381855af49150503d8060008114612e79576040519150601f19603f3d011682016040523d82523d6000602084013e612e7e565b606091505b509150915081612bd95760405162461bcd60e51b815260206004820152602360248201527f5969656c64436f6e6e6563746f723a2064656c656761746563616c6c206661696044820152621b195960ea1b606482015260840161051d565b6040516001600160a01b038316602482015260448101829052612ca590849063a9059cbb60e01b90606401612c15565b6000612f61826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166130079092919063ffffffff16565b805190915015612ca55780806020019051810190612f7f9190613728565b612ca55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161051d565b6040516001600160a01b0382166024820152612ca590839063189acdbd60e31b9060440161292f565b6060612bd9848460008585600080866001600160a01b0316858760405161302e9190613836565b60006040518083038185875af1925050503d806000811461306b576040519150601f19603f3d011682016040523d82523d6000602084013e613070565b606091505b50915091506130818783838761308c565b979650505050505050565b606083156130fb5782516000036130f4576001600160a01b0385163b6130f45760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161051d565b5081612bd9565b612bd983838151156131105781518083602001fd5b8060405162461bcd60e51b815260040161051d919061323b565b80356001600160a01b038116811461314157600080fd5b919050565b60006020828403121561315857600080fd5b610de58261312a565b60008060006040848603121561317657600080fd5b61317f8461312a565b925060208401356001600160401b038082111561319b57600080fd5b818601915086601f8301126131af57600080fd5b8135818111156131be57600080fd5b8760208285010111156131d057600080fd5b6020830194508093505050509250925092565b60005b838110156131fe5781810151838201526020016131e6565b838111156116cc5750506000910152565b600081518084526132278160208601602086016131e3565b601f01601f19169290920160200192915050565b602081526000610de5602083018461320f565b80356001600160801b038116811461314157600080fd5b80356001600160601b038116811461314157600080fd5b60008060006060848603121561329157600080fd5b61329a8461312a565b92506132a86020850161324e565b91506132b660408501613265565b90509250925092565b6000806000606084860312156132d457600080fd5b6132dd8461312a565b92506132eb6020850161312a565b9150604084013590509250925092565b6000806040838503121561330e57600080fd5b6133178361312a565b946020939093013593505050565b80356001600160401b038116811461314157600080fd5b60008060006060848603121561335157600080fd5b61335a8461312a565b925061336860208501613325565b91506132b660408501613325565b60008082840361010081121561338b57600080fd5b6133948461312a565b925060e0601f19820112156133a857600080fd5b506020830190509250929050565b600080600080608085870312156133cc57600080fd5b6133d58561312a565b93506133e36020860161312a565b92506133f16040860161324e565b91506133ff60608601613265565b905092959194509250565b60208082526018908201527f426f625661756c743a206e6f7420617574686f72697a65640000000000000000604082015260600190565b6020808252818101527f426f625661756c743a20756e737570706f7274656420636f6c6c61746572616c604082015260600190565b6020808252601b908201527f426f625661756c743a207969656c64206e6f7420656e61626c65640000000000604082015260600190565b60208082526024908201527f426f625661756c743a20746f6b656e732073686f756c642062652064696666656040820152631c995b9d60e21b606082015260800190565b60208082526026908201527f426f625661756c743a20636f6c6c61746572616c206465706f736974207375736040820152651c195b99195960d21b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561356757613567613537565b500290565b60008261358957634e487b7160e01b600052601260045260246000fd5b500490565b6000828210156135a0576135a0613537565b500390565b6000602082840312156135b757600080fd5b5051919050565b60208082526025908201527f426f625661756c743a206578636565647320617661696c61626c65206c697175604082015264696469747960d81b606082015260800190565b60208082526029908201527f426f625661756c743a20636f6c6c61746572616c207769746864726177616c206040820152681cdd5cdc195b99195960ba1b606082015260800190565b6020808252602f908201527f426f625661756c743a20696e73756666696369656e74206c697175696469747960408201526e08199bdc8818dbdb1b185d195c985b608a1b606082015260800190565b60208082526026908201527f426f625661756c743a20756e737570706f7274656420696e70757420636f6c6c604082015265185d195c985b60d21b606082015260800190565b60208082526027908201527f426f625661756c743a20756e737570706f72746564206f757470757420636f6c6040820152661b185d195c985b60ca1b606082015260800190565b60006020828403121561373a57600080fd5b81518015158114610de557600080fd5b6000821982111561375d5761375d613537565b500190565b6020808252601a908201527f426f625661756c743a20616d6f756e7420746f6f206c61726765000000000000604082015260600190565b6000602082840312156137ab57600080fd5b610de58261324e565b6000602082840312156137c657600080fd5b610de582613325565b6000602082840312156137e157600080fd5b610de582613265565b6001600160a01b0385811682528416602082015260606040820181905281018290526000828460808401376000608084840101526080601f19601f850116830101905095945050505050565b600082516138488184602087016131e3565b919091019291505056fea2646970667358221220d412e55f20965343ef1dd4e478abd06106c7fd6b935487ea9d46c1761a4fa4dc64736f6c634300080f0033000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061018e5760003560e01c80638da5cb5b116100de578063d2794f6311610097578063df791e5011610071578063df791e5014610499578063f00388f7146104ac578063f2fde38b146104bf578063fa9dbe27146104d257600080fd5b8063d2794f6314610460578063d51c049714610473578063d66e99771461048657600080fd5b80638da5cb5b14610301578063a32f386c14610312578063a5fdc5de14610325578063a909091714610405578063b124bce514610418578063cce7ec131461044d57600080fd5b80634aa066521161014b5780636c197ff5116101255780636c197ff5146102ac578063715018a6146102bf5780638a6e0249146102c75780638bd317eb146102ee57600080fd5b80634aa066521461024d57806353b609b51461026e578063676011551461028157600080fd5b806303f9c793146101935780630ee21e54146101a85780630fcff772146101f457806318a467aa1461021457806320d22739146102275780633dd0d01b1461023a575b600080fd5b6101a66101a1366004613146565b6104e5565b005b6101df6101b6366004613146565b6001600160a01b03166000908152600360205260409020600201546001600160801b0316151590565b60405190151581526020015b60405180910390f35b610207610202366004613161565b6105a0565b6040516101eb919061323b565b6101a6610222366004613146565b6106f1565b6101a661023536600461327c565b61071b565b6101a6610248366004613146565b610843565b61026061025b3660046132bf565b61086d565b6040519081526020016101eb565b61026061027c3660046132bf565b610dec565b600154610294906001600160a01b031681565b6040516001600160a01b0390911681526020016101eb565b6102606102ba3660046132fb565b61134a565b6101a6611575565b6102947f000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b81565b6101a66102fc3660046132fb565b611589565b6000546001600160a01b0316610294565b600254610294906001600160a01b031681565b6103a0610333366004613146565b6003602052600090815260409020805460018201546002909201546001600160801b0380831693600160801b938490048216936001600160601b03821693600160601b9092046001600160a01b0316928216919081046001600160401b0390811691600160c01b90041687565b604080516001600160801b03988916815296881660208801526001600160601b03909516948601949094526001600160a01b0390921660608501529390931660808301526001600160401b0392831660a08301529190911660c082015260e0016101eb565b610260610413366004613146565b6116d2565b61042b610426366004613146565b6118b3565b60408051825181526020808401519082015291810151908201526060016101eb565b61026061045b3660046132fb565b611a20565b6101a661046e36600461333c565b611c58565b6101a6610481366004613146565b611e1b565b6101a6610494366004613376565b611f61565b6102606104a73660046132bf565b6122d1565b6101a66104ba3660046132fb565b6125d4565b6101a66104cd366004613146565b6126b2565b6101a66104e03660046133b6565b61272b565b6002546001600160a01b031633148061050157506105016127f2565b6105265760405162461bcd60e51b815260040161051d9061340a565b60405180910390fd5b6001600160a01b038116600090815260036020526040902060028101546001600160801b03166105685760405162461bcd60e51b815260040161051d90613441565b6001810154815461059c918491600160601b9091046001600160a01b031690600160801b90046001600160801b0316612837565b5050565b6001546060906001600160a01b03163314806105bf57506105bf6127f2565b6105db5760405162461bcd60e51b815260040161051d9061340a565b6001600160a01b03848116600090815260036020908152604091829020825160e08101845281546001600160801b038082168352600160801b9182900481169483019490945260018301546001600160601b03811695830195909552600160601b909404909416606085015260020154908116608084018190529181046001600160401b0390811660a0850152600160c01b9091041660c08301526106925760405162461bcd60e51b815260040161051d90613441565b6106a381606001518633878761290a565b915080606001516001600160a01b0316856001600160a01b03167f388451cdba6e32008ba46b380b1f61d7b47e76bd81e07f41eba9146612d436f360405160405180910390a3509392505050565b6106f9612970565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b610723612970565b6001600160a01b038316600090815260036020526040902060028101546001600160801b03166107655760405162461bcd60e51b815260040161051d90613441565b6001810154600160601b90046001600160a01b0316806107975760405162461bcd60e51b815260040161051d90613476565b6001820180546bffffffffffffffffffffffff19166001600160601b03851617905581546001600160801b03908116600160801b9186169182021783556107e19086908390612837565b604080516001600160801b03861681526001600160601b03851660208201526001600160a01b0380841692908816917f97e7f65b045b61d192fa31c300d58a2d1f7423de3ff84b488956514d89e2897691015b60405180910390a35050505050565b61084b612970565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000826001600160a01b0316846001600160a01b0316036108a05760405162461bcd60e51b815260040161051d906134ad565b7f000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b6001600160a01b0316836001600160a01b031603610a80576001600160a01b038416600090815260036020526040902060028101546001600160801b031661091b5760405162461bcd60e51b815260040161051d90613441565b6002810154662386f26fc10000600160801b9091046001600160401b031611156109575760405162461bcd60e51b815260040161051d906134f1565b6002810154600090670de0b6b3a76400009061098390600160801b90046001600160401b03168661354d565b61098d919061356c565b9050600061099b828661358e565b60028401549091506000906001600160801b03166109c183670de0b6b3a764000061354d565b6109cb919061356c565b6040516370a0823160e01b81523060048201529091507f000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b6001600160a01b0316906370a0823190602401602060405180830381865afa158015610a32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5691906135a5565b811115610a755760405162461bcd60e51b815260040161051d906135be565b9350610de592505050565b7f000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b6001600160a01b0316846001600160a01b031603610bda576001600160a01b038316600090815260036020526040902060028101546001600160801b0316610afb5760405162461bcd60e51b815260040161051d90613441565b6002810154662386f26fc10000600160c01b9091046001600160401b03161115610b375760405162461bcd60e51b815260040161051d90613603565b6002810154600090670de0b6b3a764000090610b5c906001600160801b03168661354d565b610b66919061356c565b82549091506001600160801b0316811115610b935760405162461bcd60e51b815260040161051d9061364c565b6002820154670de0b6b3a764000090610bbc90600160c01b90046001600160401b03168361354d565b610bc6919061356c565b610bd0908261358e565b9250610de5915050565b6001600160a01b038085166000908152600360205260408082209286168252902060028201546001600160801b0316610c255760405162461bcd60e51b815260040161051d9061369b565b60028101546001600160801b0316610c4f5760405162461bcd60e51b815260040161051d906136e1565b6002820154662386f26fc10000600160801b9091046001600160401b03161115610c8b5760405162461bcd60e51b815260040161051d906134f1565b6002810154662386f26fc10000600160c01b9091046001600160401b03161115610cc75760405162461bcd60e51b815260040161051d90613603565b6002820154600090670de0b6b3a764000090610cf390600160801b90046001600160401b03168761354d565b610cfd919061356c565b90506000610d0b828761358e565b60028501549091506000906001600160801b0316610d3183670de0b6b3a764000061354d565b610d3b919061356c565b6002850154909150600090670de0b6b3a764000090610d63906001600160801b03168461354d565b610d6d919061356c565b85549091506001600160801b0316811115610d9a5760405162461bcd60e51b815260040161051d9061364c565b6002850154670de0b6b3a764000090610dc390600160c01b90046001600160401b03168361354d565b610dcd919061356c565b610dd7908261358e565b9650610de595505050505050565b9392505050565b6000826001600160a01b0316846001600160a01b031603610e1f5760405162461bcd60e51b815260040161051d906134ad565b7f000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b6001600160a01b0316836001600160a01b031603610ff5576001600160a01b038416600090815260036020526040902060028101546001600160801b0316610e9a5760405162461bcd60e51b815260040161051d90613441565b6002810154662386f26fc10000600160801b9091046001600160401b03161115610ed65760405162461bcd60e51b815260040161051d906134f1565b6040516370a0823160e01b81523060048201527f000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b6001600160a01b0316906370a0823190602401602060405180830381865afa158015610f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5e91906135a5565b831115610f7d5760405162461bcd60e51b815260040161051d906135be565b6002810154600090670de0b6b3a764000090610fa2906001600160801b03168661354d565b610fac919061356c565b6002830154909150600090610fd990600160801b90046001600160401b0316670de0b6b3a764000061358e565b610feb83670de0b6b3a764000061354d565b610a75919061356c565b7f000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b6001600160a01b0316846001600160a01b031603611142576001600160a01b038316600090815260036020526040902060028101546001600160801b03166110705760405162461bcd60e51b815260040161051d90613441565b6002810154662386f26fc10000600160c01b9091046001600160401b031611156110ac5760405162461bcd60e51b815260040161051d90613603565b60028101546000906110d690600160c01b90046001600160401b0316670de0b6b3a764000061358e565b6110e885670de0b6b3a764000061354d565b6110f2919061356c565b82549091506001600160801b031681111561111f5760405162461bcd60e51b815260040161051d9061364c565b60028201546000906001600160801b0316610feb83670de0b6b3a764000061354d565b6001600160a01b038085166000908152600360205260408082209286168252902060028201546001600160801b031661118d5760405162461bcd60e51b815260040161051d9061369b565b60028101546001600160801b03166111b75760405162461bcd60e51b815260040161051d906136e1565b6002820154662386f26fc10000600160801b9091046001600160401b031611156111f35760405162461bcd60e51b815260040161051d906134f1565b6002810154662386f26fc10000600160c01b9091046001600160401b0316111561122f5760405162461bcd60e51b815260040161051d90613603565b600281015460009061125990600160c01b90046001600160401b0316670de0b6b3a764000061358e565b61126b86670de0b6b3a764000061354d565b611275919061356c565b82549091506001600160801b03168111156112a25760405162461bcd60e51b815260040161051d9061364c565b60028201546000906001600160801b03166112c583670de0b6b3a764000061354d565b6112cf919061356c565b6002850154909150600090670de0b6b3a7640000906112f7906001600160801b03168461354d565b611301919061356c565b600286015490915060009061132e90600160801b90046001600160401b0316670de0b6b3a764000061358e565b61134083670de0b6b3a764000061354d565b610dd7919061356c565b6001600160a01b038216600090815260036020526040812060028101546001600160801b031661138c5760405162461bcd60e51b815260040161051d90613441565b6002810154662386f26fc10000600160c01b9091046001600160401b031611156113c85760405162461bcd60e51b815260040161051d90613603565b6040516323b872dd60e01b8152336004820152306024820152604481018490527f000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b6001600160a01b0316906323b872dd906064016020604051808303816000875af115801561143b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061145f9190613728565b506002810154600090670de0b6b3a764000090611485906001600160801b03168661354d565b61148f919061356c565b82549091506001600160801b03168111156114bc5760405162461bcd60e51b815260040161051d9061364c565b81546001600160801b03808216839003166001600160801b03199091161782556002820154670de0b6b3a764000090611506906001600160401b03600160c01b909104168361354d565b611510919061356c565b61151a908261358e565b90506115278533836129c4565b604080518581526020810183905233916001600160a01b038816917fa082022e93cfcd9f1da5f9236718053910f7e840da080c789c7845698dc032ff910160405180910390a3949350505050565b61157d612970565b6115876000612b45565b565b611591612970565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b6001600160a01b0316906370a0823190602401602060405180830381865afa1580156115f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161c91906135a5565b9050600082821161162d578161162f565b825b905080156116cc5760405163a9059cbb60e01b81526001600160a01b038581166004830152602482018390527f000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b169063a9059cbb906044016020604051808303816000875af11580156116a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ca9190613728565b505b50505050565b6001546000906001600160a01b03163314806116f157506116f16127f2565b61170d5760405162461bcd60e51b815260040161051d9061340a565b6001600160a01b038216600090815260036020526040902060028101546001600160801b031661174f5760405162461bcd60e51b815260040161051d90613441565b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa158015611796573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117ba91906135a5565b825460018401549192506001600160801b031690600160601b90046001600160a01b03161561182a57600183015461180290600160601b90046001600160a01b031686612b95565b61180c908361374a565b6001840154909250611827906001600160601b03168261374a565b90505b81811061183c57506000949350505050565b6000611848828461358e565b90506118558633836129c4565b60018401546040516001600160a01b03600160601b9092048216918816907f22357843602b631ef738ef8439659fbccae0f50c9f1a17abcedfafd2f785a0d6906118a29085815260200190565b60405180910390a395945050505050565b6118d760405180606001604052806000815260200160008152602001600081525090565b6001600160a01b038216600090815260036020526040902060028101546001600160801b03166119195760405162461bcd60e51b815260040161051d90613441565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa15801561195d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198191906135a5565b825280546001600160801b031660208301526001810154600160601b90046001600160a01b031615611a045760018101546119cc90600160601b90046001600160a01b031684612b95565b825183906119db90839061374a565b90525060018101546020830180516001600160601b0390921691611a0090839061374a565b9052505b60208201518251611a15919061358e565b604083015250919050565b6001600160a01b038216600090815260036020526040812060028101546001600160801b0316611a625760405162461bcd60e51b815260040161051d90613441565b6002810154662386f26fc10000600160801b9091046001600160401b03161115611a9e5760405162461bcd60e51b815260040161051d906134f1565b611ab36001600160a01b038516333086612be1565b6002810154600090670de0b6b3a764000090611adf90600160801b90046001600160401b03168661354d565b611ae9919061356c565b90506000611af7828661358e565b60028401549091506000906001600160801b0316611b1d83670de0b6b3a764000061354d565b611b27919061356c565b84549091506001600160801b0390811683011115611b575760405162461bcd60e51b815260040161051d90613762565b83546001600160801b038082168401166001600160801b031990911617845560405163a9059cbb60e01b8152336004820152602481018290526001600160a01b037f000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b169063a9059cbb906044016020604051808303816000875af1158015611be3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c079190613728565b50604080518781526020810183905233916001600160a01b038a16917f89f5adc174562e07c9c9b1cae7109bbecb21cf9d1b2847e550042b8653c54a0e910160405180910390a39695505050505050565b611c60612970565b6001600160a01b038316600090815260036020526040902060028101546001600160801b0316611ca25760405162461bcd60e51b815260040161051d90613441565b662386f26fc100006001600160401b038416111580611cd15750826001600160401b0316670de0b6b3a7640000145b611d175760405162461bcd60e51b8152602060048201526017602482015276426f625661756c743a20696e76616c696420696e46656560481b604482015260640161051d565b662386f26fc100006001600160401b038316111580611d465750816001600160401b0316670de0b6b3a7640000145b611d8d5760405162461bcd60e51b8152602060048201526018602482015277426f625661756c743a20696e76616c6964206f757446656560401b604482015260640161051d565b6002810180546001600160801b0316600160c01b6001600160401b0385811691820267ffffffffffffffff60801b191692909217600160801b928716928302179092556040805191825260208201929092526001600160a01b038616917fbacc19961151cbf3edcf4cf8653aa6017430dbe14fdc333f4e2a78229c47448a910160405180910390a250505050565b611e23612970565b6001600160a01b038116600090815260036020526040902060028101546001600160801b0316611e655760405162461bcd60e51b815260040161051d90613441565b6001810154600160601b90046001600160a01b031680611e975760405162461bcd60e51b815260040161051d90613476565b60006001830181905582546001600160801b03168355611eb78285612b95565b9050611ec4828583612c4c565b816001600160a01b0316846001600160a01b03167f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb83604051611f0991815260200190565b60405180910390a3611f1b8285612c7c565b816001600160a01b0316846001600160a01b03167f2db210ad679becb80ef14e8aad6c235b8d62bb0269252792723a6887042a60a360405160405180910390a350505050565b611f69612970565b6001600160a01b038216600090815260036020526040902060028101546001600160801b031615611fed5760405162461bcd60e51b815260206004820152602860248201527f426f625661756c743a20616c726561647920696e697469616c697a656420636f6044820152671b1b185d195c985b60c21b606482015260840161051d565b6000611fff60a0840160808501613799565b6001600160801b0316116120555760405162461bcd60e51b815260206004820152601760248201527f426f625661756c743a20696e76616c6964207072696365000000000000000000604482015260640161051d565b662386f26fc1000061206d60c0840160a085016137b4565b6001600160401b031611156120be5760405162461bcd60e51b8152602060048201526017602482015276426f625661756c743a20696e76616c696420696e46656560481b604482015260640161051d565b662386f26fc100006120d660e0840160c085016137b4565b6001600160401b031611156121285760405162461bcd60e51b8152602060048201526018602482015277426f625661756c743a20696e76616c6964206f757446656560401b604482015260640161051d565b6001600160a01b0383167fbacc19961151cbf3edcf4cf8653aa6017430dbe14fdc333f4e2a78229c47448a61216360c0850160a086016137b4565b61217360e0860160c087016137b4565b604080516001600160401b0393841681529290911660208301520160405180910390a26121a660a0830160808401613799565b6121b660c0840160a085016137b4565b6121c660e0850160c086016137b4565b6002840180546001600160801b03908116600160c01b6001600160401b039485160267ffffffffffffffff60801b191617600160801b9490931693909302919091176001600160801b03191692909116919091179055600061222e6080840160608501613146565b6001600160a01b03161461227557612275836122506080850160608601613146565b6122606040860160208701613799565b61227060608701604088016137cf565b612caa565b6001600160a01b0383167f72ef4b402b9a2c78796038c5ccfe4a0a6dda91238fdcdbf1dc7263b07ab5512c6122b060a0850160808601613799565b6040516001600160801b0390911681526020015b60405180910390a2505050565b6001600160a01b03808416600081815260036020526040808220938616808352908220919392036123145760405162461bcd60e51b815260040161051d906134ad565b60028201546001600160801b031661233e5760405162461bcd60e51b815260040161051d9061369b565b60028101546001600160801b03166123685760405162461bcd60e51b815260040161051d906136e1565b6002820154662386f26fc10000600160801b9091046001600160401b031611156123a45760405162461bcd60e51b815260040161051d906134f1565b6002810154662386f26fc10000600160c01b9091046001600160401b031611156123e05760405162461bcd60e51b815260040161051d90613603565b6123f56001600160a01b038716333087612be1565b6002820154600090670de0b6b3a76400009061242190600160801b90046001600160401b03168761354d565b61242b919061356c565b90506000612439828761358e565b84549091506001600160801b03908116820111156124695760405162461bcd60e51b815260040161051d90613762565b83546001600160801b031981166001600160801b03918216830182161785556002850154600091166124a383670de0b6b3a764000061354d565b6124ad919061356c565b6002850154909150600090670de0b6b3a7640000906124d5906001600160801b03168461354d565b6124df919061356c565b85549091506001600160801b031681111561250c5760405162461bcd60e51b815260040161051d9061364c565b84546001600160801b03808216839003166001600160801b03199091161785556002850154670de0b6b3a764000090612556906001600160401b03600160c01b909104168361354d565b612560919061356c565b61256a908261358e565b90506125778933836129c4565b604080516001600160a01b038b81168252602082018b905291810183905233918c16907fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e460629060600160405180910390a39998505050505050505050565b6001600160a01b038216600090815260036020526040902060028101546001600160801b03166126165760405162461bcd60e51b815260040161051d90613441565b61262b6001600160a01b038416333085612be1565b80546001600160801b03908116830111156126585760405162461bcd60e51b815260040161051d90613762565b80546001600160801b038082168401166001600160801b03199091161781556040518281526001600160a01b038416907fa287a305d884484886886da5686f3b9d8d30c3f3ebedd3b5fa6103ae30bcc011906020016122c4565b6126ba612970565b6001600160a01b03811661271f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161051d565b61272881612b45565b50565b612733612970565b6001600160a01b038416600090815260036020526040902060028101546001600160801b03166127755760405162461bcd60e51b815260040161051d90613441565b6001810154600160601b90046001600160a01b0316156127d75760405162461bcd60e51b815260206004820152601f60248201527f426f625661756c743a207969656c6420616c726561647920656e61626c656400604482015260640161051d565b6116ca85858585612caa565b6001600160a01b03163b151590565b60006127fc612ddd565b8061283257507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035433905b6001600160a01b0316145b905090565b6040516370a0823160e01b81523060048201526000906001600160a01b038516906370a0823190602401602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a291906135a5565b9050818111156116cc5760006128b8838361358e565b90506128c5848683612df1565b836001600160a01b0316856001600160a01b03167f0657e0c8fff72ae811b8683a3411c30ebb5098754ec5e814687711e97cbd6db28360405161083491815260200190565b60606129668663d594930f60e01b8787878760405160240161292f94939291906137ea565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612e21565b9695505050505050565b6129786127f2565b6115875760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161051d565b6001600160a01b03831660008181526003602052604080822090516370a0823160e01b81523060048201529092906370a0823190602401602060405180830381865afa158015612a18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a3c91906135a5565b905080831115612b31576001820154600160601b90046001600160a01b031680612a785760405162461bcd60e51b815260040161051d90613476565b6000612a848288612b95565b84549091506000908490612aa9908890600160801b90046001600160801b031661374a565b612ab3919061358e565b905080821015612ac05750805b6001850154612ae090600160601b90046001600160a01b03168983612c4c565b826001600160a01b0316886001600160a01b03167f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb83604051612b2591815260200190565b60405180910390a35050505b6116ca6001600160a01b0386168585612edc565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b03821660248201526000908190612bc39085906333fddd1160e21b9060440161292f565b905080806020019051810190612bd991906135a5565b949350505050565b6040516001600160a01b03808516602483015283166044820152606481018290526116cc9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612f0c565b6040516001600160a01b0383166024820152604481018290526116cc90849063f3fef3a360e01b9060640161292f565b6040516001600160a01b0382166024820152612ca590839063b42652e960e01b9060440161292f565b505050565b6001600160a01b0384166000908152600360205260409020612cd5846001600160a01b03163b151590565b612d215760405162461bcd60e51b815260206004820152601e60248201527f426f625661756c743a207969656c64206e6f74206120636f6e74726163740000604482015260640161051d565b6001600160601b0382166001600160a01b038516600160601b026bffffffffffffffffffffffff191617600182015580546001600160801b03808516600160801b029116178155612d728486612fde565b612d868585856001600160801b0316612837565b604080516001600160801b03851681526001600160601b03841660208201526001600160a01b0380871692908816917f708019cb44b26fc7e782dfbd91c4961ce197e42bbd62305799e2b50d3e8ff4fd9101610834565b6000805433906001600160a01b0316612827565b6040516001600160a01b0383166024820152604481018290526116cc908490635cdc612360e11b9060640161292f565b6060600080846001600160a01b031684604051612e3e9190613836565b600060405180830381855af49150503d8060008114612e79576040519150601f19603f3d011682016040523d82523d6000602084013e612e7e565b606091505b509150915081612bd95760405162461bcd60e51b815260206004820152602360248201527f5969656c64436f6e6e6563746f723a2064656c656761746563616c6c206661696044820152621b195960ea1b606482015260840161051d565b6040516001600160a01b038316602482015260448101829052612ca590849063a9059cbb60e01b90606401612c15565b6000612f61826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166130079092919063ffffffff16565b805190915015612ca55780806020019051810190612f7f9190613728565b612ca55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161051d565b6040516001600160a01b0382166024820152612ca590839063189acdbd60e31b9060440161292f565b6060612bd9848460008585600080866001600160a01b0316858760405161302e9190613836565b60006040518083038185875af1925050503d806000811461306b576040519150601f19603f3d011682016040523d82523d6000602084013e613070565b606091505b50915091506130818783838761308c565b979650505050505050565b606083156130fb5782516000036130f4576001600160a01b0385163b6130f45760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161051d565b5081612bd9565b612bd983838151156131105781518083602001fd5b8060405162461bcd60e51b815260040161051d919061323b565b80356001600160a01b038116811461314157600080fd5b919050565b60006020828403121561315857600080fd5b610de58261312a565b60008060006040848603121561317657600080fd5b61317f8461312a565b925060208401356001600160401b038082111561319b57600080fd5b818601915086601f8301126131af57600080fd5b8135818111156131be57600080fd5b8760208285010111156131d057600080fd5b6020830194508093505050509250925092565b60005b838110156131fe5781810151838201526020016131e6565b838111156116cc5750506000910152565b600081518084526132278160208601602086016131e3565b601f01601f19169290920160200192915050565b602081526000610de5602083018461320f565b80356001600160801b038116811461314157600080fd5b80356001600160601b038116811461314157600080fd5b60008060006060848603121561329157600080fd5b61329a8461312a565b92506132a86020850161324e565b91506132b660408501613265565b90509250925092565b6000806000606084860312156132d457600080fd5b6132dd8461312a565b92506132eb6020850161312a565b9150604084013590509250925092565b6000806040838503121561330e57600080fd5b6133178361312a565b946020939093013593505050565b80356001600160401b038116811461314157600080fd5b60008060006060848603121561335157600080fd5b61335a8461312a565b925061336860208501613325565b91506132b660408501613325565b60008082840361010081121561338b57600080fd5b6133948461312a565b925060e0601f19820112156133a857600080fd5b506020830190509250929050565b600080600080608085870312156133cc57600080fd5b6133d58561312a565b93506133e36020860161312a565b92506133f16040860161324e565b91506133ff60608601613265565b905092959194509250565b60208082526018908201527f426f625661756c743a206e6f7420617574686f72697a65640000000000000000604082015260600190565b6020808252818101527f426f625661756c743a20756e737570706f7274656420636f6c6c61746572616c604082015260600190565b6020808252601b908201527f426f625661756c743a207969656c64206e6f7420656e61626c65640000000000604082015260600190565b60208082526024908201527f426f625661756c743a20746f6b656e732073686f756c642062652064696666656040820152631c995b9d60e21b606082015260800190565b60208082526026908201527f426f625661756c743a20636f6c6c61746572616c206465706f736974207375736040820152651c195b99195960d21b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561356757613567613537565b500290565b60008261358957634e487b7160e01b600052601260045260246000fd5b500490565b6000828210156135a0576135a0613537565b500390565b6000602082840312156135b757600080fd5b5051919050565b60208082526025908201527f426f625661756c743a206578636565647320617661696c61626c65206c697175604082015264696469747960d81b606082015260800190565b60208082526029908201527f426f625661756c743a20636f6c6c61746572616c207769746864726177616c206040820152681cdd5cdc195b99195960ba1b606082015260800190565b6020808252602f908201527f426f625661756c743a20696e73756666696369656e74206c697175696469747960408201526e08199bdc8818dbdb1b185d195c985b608a1b606082015260800190565b60208082526026908201527f426f625661756c743a20756e737570706f7274656420696e70757420636f6c6c604082015265185d195c985b60d21b606082015260800190565b60208082526027908201527f426f625661756c743a20756e737570706f72746564206f757470757420636f6c6040820152661b185d195c985b60ca1b606082015260800190565b60006020828403121561373a57600080fd5b81518015158114610de557600080fd5b6000821982111561375d5761375d613537565b500190565b6020808252601a908201527f426f625661756c743a20616d6f756e7420746f6f206c61726765000000000000604082015260600190565b6000602082840312156137ab57600080fd5b610de58261324e565b6000602082840312156137c657600080fd5b610de582613325565b6000602082840312156137e157600080fd5b610de582613265565b6001600160a01b0385811682528416602082015260606040820181905281018290526000828460808401376000608084840101526080601f19601f850116830101905095945050505050565b600082516138488184602087016131e3565b919091019291505056fea2646970667358221220d412e55f20965343ef1dd4e478abd06106c7fd6b935487ea9d46c1761a4fa4dc64736f6c634300080f0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b
-----Decoded View---------------
Arg [0] : _bobToken (address): 0xB0B195aEFA3650A6908f15CdaC7D92F8a5791B0B
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000b0b195aefa3650a6908f15cdac7d92f8a5791b0b
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.