Polygon Sponsored slots available. Book your slot here!
Overview
POL Balance
0 POL
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:
F2FujiVault
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 500 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import "./abstracts/vault/VaultBaseUpgradeable.sol"; import "./interfaces/IVault.sol"; import "./interfaces/IHarvester.sol"; import "./interfaces/ISwapper.sol"; import "./interfaces/IERC20Extended.sol"; import "./interfaces/IFujiAdmin.sol"; import "./interfaces/IFujiOracle.sol"; import "./interfaces/IFujiERC1155.sol"; import "./interfaces/IProvider.sol"; import "./libraries/Errors.sol"; import "./libraries/LibUniversalERC20Upgradeable.sol"; /** * @dev Contract for the interaction of Fuji users with the Fuji protocol. * - Performs deposit, withdraw, borrow and payback functions. * - Contains the fallback logic to perform a switch of providers. */ contract F2FujiVault is VaultBaseUpgradeable, ReentrancyGuardUpgradeable, IVault { using SafeERC20Upgradeable for IERC20Upgradeable; using LibUniversalERC20Upgradeable for IERC20Upgradeable; address public constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // Safety factor Factor public safetyF; // Collateralization factor Factor public collatF; // Protocol Fee factor Factor public override protocolFee; // Bonus factor for liquidation Factor public bonusLiqF; //State variables address[] public providers; address public override activeProvider; IFujiAdmin private _fujiAdmin; address public override fujiERC1155; IFujiOracle public oracle; string public name; uint8 internal _collateralAssetDecimals; uint8 internal _borrowAssetDecimals; uint256 public constant ONE_YEAR = 60 * 60 * 24 * 365; mapping(address => uint256) internal _userFeeTimestamps; // to be used for protocol fee calculation uint256 public remainingProtocolFee; /** * @dev Throws if caller is not the 'owner' or the '_controller' address stored in {FujiAdmin} */ modifier isAuthorized() { require( msg.sender == owner() || msg.sender == _fujiAdmin.getController(), Errors.VL_NOT_AUTHORIZED ); _; } /** * @dev Throws if caller is not the '_flasher' address stored in {FujiAdmin} */ modifier onlyFlash() { require(msg.sender == _fujiAdmin.getFlasher(), Errors.VL_NOT_AUTHORIZED); _; } /** * @dev Throws if caller is not the '_fliquidator' address stored in {FujiAdmin} */ modifier onlyFliquidator() { require(msg.sender == _fujiAdmin.getFliquidator(), Errors.VL_NOT_AUTHORIZED); _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() initializer {} /** * @dev Initializes the contract by setting: * - Type of collateral and borrow asset of this vault. * - Addresses for fujiAdmin, _oracle. */ function initialize( address _fujiadmin, address _oracle, address _collateralAsset, address _borrowAsset ) external initializer { require( _fujiadmin != address(0) && _oracle != address(0) && _collateralAsset != address(0) && _borrowAsset != address(0), Errors.VL_ZERO_ADDR ); __Ownable_init(); __Pausable_init(); __ReentrancyGuard_init(); _fujiAdmin = IFujiAdmin(_fujiadmin); oracle = IFujiOracle(_oracle); vAssets.collateralAsset = _collateralAsset; vAssets.borrowAsset = _borrowAsset; string memory collateralSymbol; string memory borrowSymbol; if (_collateralAsset == NATIVE) { collateralSymbol = "NATIVE"; _collateralAssetDecimals = 18; } else { collateralSymbol = IERC20Extended(_collateralAsset).symbol(); _collateralAssetDecimals = IERC20Extended(_collateralAsset).decimals(); } if (_borrowAsset == NATIVE) { borrowSymbol = "NATIVE"; _borrowAssetDecimals = 18; } else { borrowSymbol = IERC20Extended(_borrowAsset).symbol(); _borrowAssetDecimals = IERC20Extended(_borrowAsset).decimals(); } name = string(abi.encodePacked("Vault", collateralSymbol, borrowSymbol)); // 1.05 safetyF.a = 21; safetyF.b = 20; // 1.269 collatF.a = 80; collatF.b = 63; // 0.05 bonusLiqF.a = 1; bonusLiqF.b = 20; protocolFee.a = 1; protocolFee.b = 1000; } receive() external payable {} //Core functions /** * @dev Deposits collateral and borrows underlying in a single function call from activeProvider * @param _collateralAmount: amount to be deposited * @param _borrowAmount: amount to be borrowed */ function depositAndBorrow(uint256 _collateralAmount, uint256 _borrowAmount) external payable { updateF1155Balances(); _internalDeposit(_collateralAmount); _internalBorrow(_borrowAmount); } /** * @dev Paybacks the underlying asset and withdraws collateral in a single function call from activeProvider * @param _paybackAmount: amount of underlying asset to be payback, pass -1 to pay full amount * @param _collateralAmount: amount of collateral to be withdrawn, pass -1 to withdraw maximum amount */ function paybackAndWithdraw(int256 _paybackAmount, int256 _collateralAmount) external payable { updateF1155Balances(); _internalPayback(_paybackAmount); _internalWithdraw(_collateralAmount); } /** * @dev Deposit Vault's type collateral to activeProvider * call Controller checkrates * @param _collateralAmount: to be deposited * Emits a {Deposit} event. */ function deposit(uint256 _collateralAmount) public payable override { updateF1155Balances(); _internalDeposit(_collateralAmount); } /** * @dev Withdraws Vault's type collateral from activeProvider * call Controller checkrates - by normal users * @param _withdrawAmount: amount of collateral to withdraw * otherwise pass any 'negative number' to withdraw maximum amount possible of collateral (including safety factors) * Emits a {Withdraw} event. */ function withdraw(int256 _withdrawAmount) public override nonReentrant { updateF1155Balances(); _internalWithdraw(_withdrawAmount); } /** * @dev Withdraws Vault's type collateral from activeProvider * call Controller checkrates - by Fliquidator * @param _withdrawAmount: amount of collateral to withdraw * otherwise pass -1 to withdraw maximum amount possible of collateral (including safety factors) * Emits a {Withdraw} event. */ function withdrawLiq(int256 _withdrawAmount) external override nonReentrant onlyFliquidator { // Logic used when called by Fliquidator _withdraw(uint256(_withdrawAmount), address(activeProvider)); IERC20Upgradeable(vAssets.collateralAsset).univTransfer( payable(msg.sender), uint256(_withdrawAmount) ); } /** * @dev Borrows Vault's type underlying amount from activeProvider * @param _borrowAmount: token amount of underlying to borrow * Emits a {Borrow} event. */ function borrow(uint256 _borrowAmount) public override nonReentrant { updateF1155Balances(); _internalBorrow(_borrowAmount); } /** * @dev Paybacks Vault's type underlying to activeProvider - called by users * @param _repayAmount: token amount of underlying to repay, or * pass any 'negative number' to repay full ammount * Emits a {Repay} event. */ function payback(int256 _repayAmount) public payable override { updateF1155Balances(); _internalPayback(_repayAmount); } /** * @dev Paybacks Vault's type underlying to activeProvider * @param _repayAmount: token amount of underlying to repay, or pass -1 to repay full ammount * Emits a {Repay} event. */ function paybackLiq(address[] memory _users, uint256 _repayAmount) external payable override onlyFliquidator { // calculate protocol fee uint256 _fee = 0; for (uint256 i = 0; i < _users.length; i++) { if (_users[i] != address(0)) { _userFeeTimestamps[_users[i]] = block.timestamp; uint256 debtPrincipal = IFujiERC1155(fujiERC1155).balanceOf(_users[i], vAssets.borrowID); _fee += _userProtocolFee(_users[i], debtPrincipal); } } // Logic used when called by Fliquidator _payback(_repayAmount - _fee, address(activeProvider)); // Update protocol fees remainingProtocolFee += _fee; } /** * @dev Changes Vault debt and collateral to newProvider, called by Flasher * @param _newProvider new provider's address * @param _flashLoanAmount amount of flashloan underlying to repay Flashloan * Emits a {Switch} event. */ function executeSwitch( address _newProvider, uint256 _flashLoanAmount, uint256 _fee ) external payable override onlyFlash whenNotPaused { // Check '_newProvider' is a valid provider bool validProvider; for (uint256 i = 0; i < providers.length; i++) { if (_newProvider == providers[i]) { validProvider = true; } } if (!validProvider) { revert(Errors.VL_INVALID_NEW_PROVIDER); } // Compute Ratio of transfer before payback uint256 ratio = (_flashLoanAmount * 1e18) / (IProvider(activeProvider).getBorrowBalance(vAssets.borrowAsset)); // Payback current provider _payback(_flashLoanAmount, activeProvider); // Withdraw collateral proportional ratio from current provider uint256 collateraltoMove = (IProvider(activeProvider).getDepositBalance( vAssets.collateralAsset ) * ratio) / 1e18; _withdraw(collateraltoMove, activeProvider); // Deposit to the new provider _deposit(collateraltoMove, _newProvider); // Borrow from the new provider, borrowBalance + premium _borrow(_flashLoanAmount + _fee, _newProvider); // return borrowed amount to Flasher IERC20Upgradeable(vAssets.borrowAsset).univTransfer( payable(msg.sender), _flashLoanAmount + _fee ); emit Switch(activeProvider, _newProvider, _flashLoanAmount, collateraltoMove); } // Setter, change state functions /** * @dev Sets the fujiAdmin Address * @param _newFujiAdmin: FujiAdmin Contract Address * Emits a {FujiAdminChanged} event. */ function setFujiAdmin(address _newFujiAdmin) external onlyOwner { require(_newFujiAdmin != address(0), Errors.VL_ZERO_ADDR); _fujiAdmin = IFujiAdmin(_newFujiAdmin); emit FujiAdminChanged(_newFujiAdmin); } /** * @dev Sets a new active provider for the Vault * @param _provider: fuji address of the new provider * Emits a {SetActiveProvider} event. */ function setActiveProvider(address _provider) external override isAuthorized { require(_provider != address(0), Errors.VL_ZERO_ADDR); activeProvider = _provider; emit SetActiveProvider(_provider); } // Administrative functions /** * @dev Sets a fujiERC1155 Collateral and Debt Asset manager for this vault and initializes it. * @param _fujiERC1155: fuji ERC1155 address * Emits a {F1155Changed} event. */ function setFujiERC1155(address _fujiERC1155) external isAuthorized { require(_fujiERC1155 != address(0), Errors.VL_ZERO_ADDR); fujiERC1155 = _fujiERC1155; vAssets.collateralID = IFujiERC1155(_fujiERC1155).addInitializeAsset( IFujiERC1155.AssetType.collateralToken, address(this) ); vAssets.borrowID = IFujiERC1155(_fujiERC1155).addInitializeAsset( IFujiERC1155.AssetType.debtToken, address(this) ); emit F1155Changed(_fujiERC1155); } /** * @dev Set Factors "a" and "b" for a Struct Factor. * @param _newFactorA: Nominator * @param _newFactorB: Denominator * @param _type: 0 for "safetyF", 1 for "collatF", 2 for "protocolFee", 3 for "bonusLiqF" * Emits a {FactorChanged} event. * Requirements: * - _newFactorA and _newFactorB should be non-zero values. * - For safetyF; a/b, should be > 1. * - For collatF; a/b, should be > 1. * - For bonusLiqF; a/b should be < 1. * - For protocolFee; a/b should be < 1. */ function setFactor( uint64 _newFactorA, uint64 _newFactorB, FactorType _type ) external isAuthorized { if (_type == FactorType.Safety) { require(_newFactorA > _newFactorB, Errors.RF_INVALID_RATIO_VALUES); safetyF.a = _newFactorA; safetyF.b = _newFactorB; } else if (_type == FactorType.Collateralization) { require(_newFactorA > _newFactorB, Errors.RF_INVALID_RATIO_VALUES); collatF.a = _newFactorA; collatF.b = _newFactorB; } else if (_type == FactorType.ProtocolFee) { require(_newFactorA < _newFactorB, Errors.RF_INVALID_RATIO_VALUES); protocolFee.a = _newFactorA; protocolFee.b = _newFactorB; } else if (_type == FactorType.BonusLiquidation) { require(_newFactorA < _newFactorB, Errors.RF_INVALID_RATIO_VALUES); bonusLiqF.a = _newFactorA; bonusLiqF.b = _newFactorB; } else { revert(Errors.VL_INVALID_FACTOR); } emit FactorChanged(_type, _newFactorA, _newFactorB); } /** * @dev Sets the Oracle address (Must Comply with AggregatorV3Interface) * @param _oracle: new Oracle address * Emits a {OracleChanged} event. */ function setOracle(address _oracle) external isAuthorized { require(_oracle != address(0), Errors.VL_ZERO_ADDR); oracle = IFujiOracle(_oracle); emit OracleChanged(_oracle); } /** * @dev Set providers to the Vault * @param _providers: new providers' addresses * Emits a {ProvidersChanged} event. */ function setProviders(address[] calldata _providers) external isAuthorized { for (uint256 i = 0; i < _providers.length; i++) { require(_providers[i] != address(0), Errors.VL_ZERO_ADDR); } providers = _providers; emit ProvidersChanged(_providers); } /** * @dev External Function to call updateState in F1155 */ function updateF1155Balances() public override { IFujiERC1155(fujiERC1155).updateState( vAssets.borrowID, IProvider(activeProvider).getBorrowBalance(vAssets.borrowAsset) ); IFujiERC1155(fujiERC1155).updateState( vAssets.collateralID, IProvider(activeProvider).getDepositBalance(vAssets.collateralAsset) ); } //Getter Functions /** * @dev Returns an array of the Vault's providers */ function getProviders() external view override returns (address[] memory) { return providers; } /** * @dev Returns an amount to be paid as bonus for liquidation * @param _amount: Vault underlying type intended to be liquidated */ function getLiquidationBonusFor(uint256 _amount) external view override returns (uint256) { return (_amount * bonusLiqF.a) / bonusLiqF.b; } /** * @dev Returns the amount of collateral needed, including or not safety factors * @param _amount: Vault underlying type intended to be borrowed * @param _withFactors: Inidicate if computation should include safety_Factors */ function getNeededCollateralFor(uint256 _amount, bool _withFactors) public view override returns (uint256) { // Get exchange rate uint256 price = oracle.getPriceOf( vAssets.collateralAsset, vAssets.borrowAsset, _collateralAssetDecimals ); uint256 minimumReq = (_amount * price) / (10**uint256(_borrowAssetDecimals)); if (_withFactors) { return (minimumReq * (collatF.a) * (safetyF.a)) / (collatF.b) / (safetyF.b); } else { return minimumReq; } } /** * @dev Returns the borrow balance of the Vault's underlying at a particular provider * @param _provider: address of a provider */ function borrowBalance(address _provider) external view override returns (uint256) { return IProvider(_provider).getBorrowBalance(vAssets.borrowAsset); } /** * @dev Returns the deposit balance of the Vault's type collateral at a particular provider * @param _provider: address of a provider */ function depositBalance(address _provider) external view override returns (uint256) { return IProvider(_provider).getDepositBalance(vAssets.collateralAsset); } /** * @dev Returns the total debt of a user * @param _user: address of a user * @return the total debt of a user including the protocol fee */ function userDebtBalance(address _user) external view override returns (uint256) { uint256 debtPrincipal = IFujiERC1155(fujiERC1155).balanceOf(_user, vAssets.borrowID); uint256 fee = (debtPrincipal * (block.timestamp - _userFeeTimestamps[_user]) * protocolFee.a) / protocolFee.b / ONE_YEAR; return debtPrincipal + fee; } /** * @dev Returns the protocol fee of a user * @param _user: address of a user * @return the protocol fee of a user */ function userProtocolFee(address _user) external view override returns (uint256) { uint256 debtPrincipal = IFujiERC1155(fujiERC1155).balanceOf(_user, vAssets.borrowID); return _userProtocolFee(_user, debtPrincipal); } /** * @dev Returns the collateral asset balance of a user * @param _user: address of a user * @return the collateral asset balance */ function userDepositBalance(address _user) external view override returns (uint256) { return IFujiERC1155(fujiERC1155).balanceOf(_user, vAssets.collateralID); } /** * @dev Harvests the Rewards from baseLayer Protocols * @param _farmProtocolNum: number per VaultHarvester Contract for specific farm * @param _data: the additional data to be used for harvest */ function harvestRewards(uint256 _farmProtocolNum, bytes memory _data) external onlyOwner { (address tokenReturned, IHarvester.Transaction memory harvestTransaction) = IHarvester( _fujiAdmin.getVaultHarvester() ).getHarvestTransaction(_farmProtocolNum, _data); // Claim rewards (bool success, ) = harvestTransaction.to.call(harvestTransaction.data); require(success, "failed to harvest rewards"); if (tokenReturned != address(0)) { uint256 tokenBal = IERC20Upgradeable(tokenReturned).univBalanceOf(address(this)); require(tokenReturned != address(0) && tokenBal > 0, Errors.VL_HARVESTING_FAILED); ISwapper.Transaction memory swapTransaction = ISwapper(_fujiAdmin.getSwapper()) .getSwapTransaction(tokenReturned, vAssets.collateralAsset, tokenBal); // Approve rewards if (tokenReturned != NATIVE) { IERC20Upgradeable(tokenReturned).univApprove(swapTransaction.to, tokenBal); } // Swap rewards -> collateralAsset (success, ) = swapTransaction.to.call{ value: swapTransaction.value }(swapTransaction.data); require(success, "failed to swap rewards"); _deposit( IERC20Upgradeable(vAssets.collateralAsset).univBalanceOf(address(this)), address(activeProvider) ); updateF1155Balances(); } } /** * @dev Withdraws all the collected Fuji fees in this vault. * NOTE: Fuji fee is charged to all users * as a service for the loan cost optimization. * It is a percentage (defined in 'protocolFee') on top of the users 'debtPrincipal'. * Requirements: * - Must send all fees amount collected to the Fuji treasury. */ function withdrawProtocolFee() external nonReentrant { IERC20Upgradeable(vAssets.borrowAsset).univTransfer( payable(IFujiAdmin(_fujiAdmin).getTreasury()), remainingProtocolFee ); remainingProtocolFee = 0; } // Internal Functions /** * @dev Returns de amount of accrued of Fuji fee by user. * @param _user: user to whom Fuji fee will be computed. * @param _debtPrincipal: current user's debt. */ function _userProtocolFee(address _user, uint256 _debtPrincipal) internal view returns (uint256) { return (_debtPrincipal * (block.timestamp - _userFeeTimestamps[_user]) * protocolFee.a) / protocolFee.b / ONE_YEAR; } /** * @dev Internal function handling logic for {deposit} without 'updateState' call * See {deposit} */ function _internalDeposit(uint256 _collateralAmount) internal { if (vAssets.collateralAsset == NATIVE) { require(msg.value == _collateralAmount && _collateralAmount != 0, Errors.VL_AMOUNT_ERROR); } else { require(_collateralAmount != 0, Errors.VL_AMOUNT_ERROR); IERC20Upgradeable(vAssets.collateralAsset).safeTransferFrom( msg.sender, address(this), _collateralAmount ); } // Delegate Call Deposit to current provider _deposit(_collateralAmount, address(activeProvider)); // Collateral Management IFujiERC1155(fujiERC1155).mint(msg.sender, vAssets.collateralID, _collateralAmount); emit Deposit(msg.sender, vAssets.collateralAsset, _collateralAmount); } /** * @dev Internal function handling logic for {withdraw} without 'updateState' call * See {withdraw} */ function _internalWithdraw(int256 _withdrawAmount) internal { // Get User Collateral in this Vault uint256 providedCollateral = IFujiERC1155(fujiERC1155).balanceOf( msg.sender, vAssets.collateralID ); // Check User has collateral require(providedCollateral > 0, Errors.VL_INVALID_COLLATERAL); // Get Required Collateral with Factors to maintain debt position healthy uint256 neededCollateral = getNeededCollateralFor( IFujiERC1155(fujiERC1155).balanceOf(msg.sender, vAssets.borrowID), true ); uint256 amountToWithdraw = _withdrawAmount < 0 ? providedCollateral - neededCollateral : uint256(_withdrawAmount); // Check Withdrawal amount, and that it will not fall undercollaterized. require( amountToWithdraw != 0 && providedCollateral - amountToWithdraw >= neededCollateral, Errors.VL_INVALID_WITHDRAW_AMOUNT ); uint256 balanceBefore = IERC20Upgradeable(vAssets.collateralAsset).univBalanceOf(address(this)); // Delegate Call Withdraw to current provider _withdraw(amountToWithdraw, address(activeProvider)); amountToWithdraw = IERC20Upgradeable(vAssets.collateralAsset).univBalanceOf(address(this)) - balanceBefore; // Collateral Management before Withdraw Operation IFujiERC1155(fujiERC1155).burn(msg.sender, vAssets.collateralID, amountToWithdraw); // Transer Assets to User IERC20Upgradeable(vAssets.collateralAsset).univTransfer(payable(msg.sender), amountToWithdraw); emit Withdraw(msg.sender, vAssets.collateralAsset, amountToWithdraw); } /** * @dev Internal function handling logic for {borrow} without 'updateState' call * See {borrow} */ function _internalBorrow(uint256 _borrowAmount) internal { uint256 providedCollateral = IFujiERC1155(fujiERC1155).balanceOf( msg.sender, vAssets.collateralID ); uint256 debtPrincipal = IFujiERC1155(fujiERC1155).balanceOf(msg.sender, vAssets.borrowID); uint256 totalBorrow = _borrowAmount + debtPrincipal; // Get Required Collateral with Factors to maintain debt position healthy uint256 neededCollateral = getNeededCollateralFor(totalBorrow, true); // Check Provided Collateral is not Zero, and greater than needed to maintain healthy position require( _borrowAmount != 0 && providedCollateral > neededCollateral, Errors.VL_INVALID_BORROW_AMOUNT ); uint256 balanceBefore = IERC20Upgradeable(vAssets.borrowAsset).univBalanceOf(address(this)); // Delegate Call Borrow to current provider _borrow(_borrowAmount, address(activeProvider)); _borrowAmount = IERC20Upgradeable(vAssets.borrowAsset).univBalanceOf(address(this)) - balanceBefore; totalBorrow = _borrowAmount + debtPrincipal; // Update timestamp for fee calculation uint256 userFee = (debtPrincipal * (block.timestamp - _userFeeTimestamps[msg.sender]) * protocolFee.a) / protocolFee.b / ONE_YEAR; _userFeeTimestamps[msg.sender] = block.timestamp - (userFee * ONE_YEAR * protocolFee.a) / protocolFee.b / totalBorrow; // Debt Management IFujiERC1155(fujiERC1155).mint(msg.sender, vAssets.borrowID, _borrowAmount); // Transer Assets to User IERC20Upgradeable(vAssets.borrowAsset).univTransfer(payable(msg.sender), _borrowAmount); emit Borrow(msg.sender, vAssets.borrowAsset, _borrowAmount); } /** * @dev Internal function handling logic for {payback} without 'updateState' call * See {payback} */ function _internalPayback(int256 _repayAmount) internal { uint256 debtBalance = IFujiERC1155(fujiERC1155).balanceOf(msg.sender, vAssets.borrowID); uint256 userFee = _userProtocolFee(msg.sender, debtBalance); // Check User Debt is greater than Zero and amount is not Zero require(uint256(_repayAmount) > userFee && debtBalance > 0, Errors.VL_NO_DEBT_TO_PAYBACK); // If passed argument amount is negative do MAX uint256 amountToPayback = _repayAmount < 0 ? debtBalance + userFee : uint256(_repayAmount); if (vAssets.borrowAsset == NATIVE) { require(msg.value >= amountToPayback, Errors.VL_AMOUNT_ERROR); if (msg.value > amountToPayback) { IERC20Upgradeable(vAssets.borrowAsset).univTransfer( payable(msg.sender), msg.value - amountToPayback ); } } else { // Check User Allowance require( IERC20Upgradeable(vAssets.borrowAsset).allowance(msg.sender, address(this)) >= amountToPayback, Errors.VL_MISSING_ERC20_ALLOWANCE ); // Transfer Asset from User to Vault IERC20Upgradeable(vAssets.borrowAsset).safeTransferFrom( msg.sender, address(this), amountToPayback ); } // Delegate Call Payback to current provider _payback(amountToPayback - userFee, address(activeProvider)); // Debt Management IFujiERC1155(fujiERC1155).burn(msg.sender, vAssets.borrowID, amountToPayback - userFee); // Update protocol fees _userFeeTimestamps[msg.sender] = block.timestamp; remainingProtocolFee += userFee; emit Payback(msg.sender, vAssets.borrowAsset, amountToPayback); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// 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 IERC20Upgradeable { /** * @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/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20Upgradeable.sol"; import "../../../utils/AddressUpgradeable.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 SafeERC20Upgradeable { using AddressUpgradeable for address; function safeTransfer( IERC20Upgradeable token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20Upgradeable 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( IERC20Upgradeable 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( IERC20Upgradeable 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( IERC20Upgradeable token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20Upgradeable 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 pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import "../../interfaces/IVaultControl.sol"; import "../../libraries/Errors.sol"; /** * @dev Contract that is inherited by FujiVaults * contains delegate call functions to providers and {Pausable} guards * */ abstract contract VaultControlUpgradeable is OwnableUpgradeable, PausableUpgradeable { // Vault Struct for Managed Assets IVaultControl.VaultAssets public vAssets; // Pause Functions /** * @dev Emergency Call to stop all basic money flow functions. */ function pause() public onlyOwner { _pause(); } /** * @dev Emergency Call to stop all basic money flow functions. */ function unpause() public onlyOwner { _unpause(); } } contract VaultBaseUpgradeable is VaultControlUpgradeable { using AddressUpgradeable for address; // Internal functions /** * @dev Executes deposit operation with delegatecall. * @param _amount: amount to be deposited * @param _provider: address of provider to be used */ function _deposit(uint256 _amount, address _provider) internal { bytes memory data = abi.encodeWithSignature( "deposit(address,uint256)", vAssets.collateralAsset, _amount ); _execute(_provider, data); } /** * @dev Executes withdraw operation with delegatecall. * @param _amount: amount to be withdrawn * @param _provider: address of provider to be used */ function _withdraw(uint256 _amount, address _provider) internal { bytes memory data = abi.encodeWithSignature( "withdraw(address,uint256)", vAssets.collateralAsset, _amount ); _execute(_provider, data); } /** * @dev Executes borrow operation with delegatecall. * @param _amount: amount to be borrowed * @param _provider: address of provider to be used */ function _borrow(uint256 _amount, address _provider) internal { bytes memory data = abi.encodeWithSignature( "borrow(address,uint256)", vAssets.borrowAsset, _amount ); _execute(_provider, data); } /** * @dev Executes payback operation with delegatecall. * @param _amount: amount to be paid back * @param _provider: address of provider to be used */ function _payback(uint256 _amount, address _provider) internal { bytes memory data = abi.encodeWithSignature( "payback(address,uint256)", vAssets.borrowAsset, _amount ); _execute(_provider, data); } /** * @dev Returns byte response of delegatcalls */ function _execute(address _target, bytes memory _data) private whenNotPaused returns (bytes memory response) { // This is the same logic of functionDelegateCall provided by openzeppelin. // We copy the code here because of oz-upgrades-unsafe-allow for delegatecall. require(_target.isContract(), Errors.VL_NOT_A_CONTRACT); /// @custom:oz-upgrades-unsafe-allow delegatecall (bool success, bytes memory returndata) = _target.delegatecall(_data); return AddressUpgradeable.verifyCallResult(success, returndata, "delegate call to provider failed"); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IVault { // Vault Events /** * @dev Log a deposit transaction done by a user */ event Deposit(address indexed userAddrs, address indexed asset, uint256 amount); /** * @dev Log a withdraw transaction done by a user */ event Withdraw(address indexed userAddrs, address indexed asset, uint256 amount); /** * @dev Log a borrow transaction done by a user */ event Borrow(address indexed userAddrs, address indexed asset, uint256 amount); /** * @dev Log a payback transaction done by a user */ event Payback(address indexed userAddrs, address indexed asset, uint256 amount); /** * @dev Log a switch from provider to new provider in vault */ event Switch( address fromProviderAddrs, address toProviderAddr, uint256 debtamount, uint256 collattamount ); /** * @dev Log a change in active provider */ event SetActiveProvider(address newActiveProviderAddress); /** * @dev Log a change in the array of provider addresses */ event ProvidersChanged(address[] newProviderArray); /** * @dev Log a change in F1155 address */ event F1155Changed(address newF1155Address); /** * @dev Log a change in fuji admin address */ event FujiAdminChanged(address newFujiAdmin); /** * @dev Log a change in the factor values */ event FactorChanged(FactorType factorType, uint64 newFactorA, uint64 newFactorB); /** * @dev Log a change in the oracle address */ event OracleChanged(address newOracle); enum FactorType { Safety, Collateralization, ProtocolFee, BonusLiquidation } struct Factor { uint64 a; uint64 b; } // Core Vault Functions function deposit(uint256 _collateralAmount) external payable; function withdraw(int256 _withdrawAmount) external; function withdrawLiq(int256 _withdrawAmount) external; function borrow(uint256 _borrowAmount) external; function payback(int256 _repayAmount) external payable; function paybackLiq(address[] memory _users, uint256 _repayAmount) external payable; function executeSwitch( address _newProvider, uint256 _flashLoanDebt, uint256 _fee ) external payable; //Getter Functions function activeProvider() external view returns (address); function borrowBalance(address _provider) external view returns (uint256); function depositBalance(address _provider) external view returns (uint256); function userDebtBalance(address _user) external view returns (uint256); function userProtocolFee(address _user) external view returns (uint256); function userDepositBalance(address _user) external view returns (uint256); function getNeededCollateralFor(uint256 _amount, bool _withFactors) external view returns (uint256); function getLiquidationBonusFor(uint256 _amount) external view returns (uint256); function getProviders() external view returns (address[] memory); function fujiERC1155() external view returns (address); //Setter Functions function setActiveProvider(address _provider) external; function updateF1155Balances() external; function protocolFee() external view returns (uint64, uint64); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IHarvester { struct Transaction { address to; bytes data; } function getHarvestTransaction(uint256 _farmProtocolNum, bytes memory _data) external returns (address claimedToken, Transaction memory transaction); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ISwapper { struct Transaction { address to; bytes data; uint256 value; } function getSwapTransaction( address assetFrom, address assetTo, uint256 amount ) external returns (Transaction memory transaction); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IERC20Extended { function symbol() external view returns (string memory); function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IFujiAdmin { // FujiAdmin Events /** * @dev Log change of flasher address */ event FlasherChanged(address newFlasher); /** * @dev Log change of fliquidator address */ event FliquidatorChanged(address newFliquidator); /** * @dev Log change of treasury address */ event TreasuryChanged(address newTreasury); /** * @dev Log change of controller address */ event ControllerChanged(address newController); /** * @dev Log change of vault harvester address */ event VaultHarvesterChanged(address newHarvester); /** * @dev Log change of swapper address */ event SwapperChanged(address newSwapper); /** * @dev Log change of vault address permission */ event VaultPermitChanged(address vaultAddress, bool newPermit); function validVault(address _vaultAddr) external view returns (bool); function getFlasher() external view returns (address); function getFliquidator() external view returns (address); function getController() external view returns (address); function getTreasury() external view returns (address payable); function getVaultHarvester() external view returns (address); function getSwapper() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IFujiOracle { // FujiOracle Events /** * @dev Log a change in price feed address for asset address */ event AssetPriceFeedChanged(address asset, address newPriceFeedAddress); function getPriceOf( address _collateralAsset, address _borrowAsset, uint8 _decimals ) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IFujiERC1155 { //Asset Types enum AssetType { //uint8 = 0 collateralToken, //uint8 = 1 debtToken } //General Getter Functions function getAssetID(AssetType _type, address _assetAddr) external view returns (uint256); function qtyOfManagedAssets() external view returns (uint64); function balanceOf(address _account, uint256 _id) external view returns (uint256); // function splitBalanceOf(address account,uint256 _AssetID) external view returns (uint256,uint256); // function balanceOfBatchType(address account, AssetType _Type) external view returns (uint256); //Permit Controlled Functions function mint( address _account, uint256 _id, uint256 _amount ) external; function burn( address _account, uint256 _id, uint256 _amount ) external; function updateState(uint256 _assetID, uint256 _newBalance) external; function addInitializeAsset(AssetType _type, address _addr) external returns (uint64); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IProvider { //Basic Core Functions function deposit(address _collateralAsset, uint256 _collateralAmount) external payable; function borrow(address _borrowAsset, uint256 _borrowAmount) external payable; function withdraw(address _collateralAsset, uint256 _collateralAmount) external payable; function payback(address _borrowAsset, uint256 _borrowAmount) external payable; // returns the borrow annualized rate for an asset in ray (1e27) //Example 8.5% annual interest = 0.085 x 10^27 = 85000000000000000000000000 or 85*(10**24) function getBorrowRateFor(address _asset) external view returns (uint256); function getBorrowBalance(address _asset) external view returns (uint256); function getDepositBalance(address _asset) external view returns (uint256); function getBorrowBalanceOf(address _asset, address _who) external returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Errors library * @author Fuji * @notice Defines the error messages emitted by the different contracts * @dev Error messages prefix glossary: * - VL = Validation Logic 100 series * - MATH = Math libraries 200 series * - RF = Refinancing 300 series * - VLT = vault 400 series * - SP = Special 900 series */ library Errors { //Errors string public constant VL_INDEX_OVERFLOW = "100"; // index overflows uint128 string public constant VL_INVALID_MINT_AMOUNT = "101"; //invalid amount to mint string public constant VL_INVALID_BURN_AMOUNT = "102"; //invalid amount to burn string public constant VL_AMOUNT_ERROR = "103"; //Input value >0, and for ETH msg.value and amount shall match string public constant VL_INVALID_WITHDRAW_AMOUNT = "104"; //Withdraw amount exceeds provided collateral, or falls undercollaterized string public constant VL_INVALID_BORROW_AMOUNT = "105"; //Borrow amount does not meet collaterization string public constant VL_NO_DEBT_TO_PAYBACK = "106"; //Msg sender has no debt amount to be payback string public constant VL_MISSING_ERC20_ALLOWANCE = "107"; //Msg sender has not approved ERC20 full amount to transfer string public constant VL_USER_NOT_LIQUIDATABLE = "108"; //User debt position is not liquidatable string public constant VL_DEBT_LESS_THAN_AMOUNT = "109"; //User debt is less than amount to partial close string public constant VL_PROVIDER_ALREADY_ADDED = "110"; // Provider is already added in Provider Array string public constant VL_NOT_AUTHORIZED = "111"; //Not authorized string public constant VL_INVALID_COLLATERAL = "112"; //There is no Collateral, or Collateral is not in active in vault string public constant VL_NO_ERC20_BALANCE = "113"; //User does not have ERC20 balance string public constant VL_INPUT_ERROR = "114"; //Check inputs. For ERC1155 batch functions, array sizes should match. string public constant VL_ASSET_EXISTS = "115"; //Asset intended to be added already exists in FujiERC1155 string public constant VL_ZERO_ADDR_1155 = "116"; //ERC1155: balance/transfer for zero address string public constant VL_NOT_A_CONTRACT = "117"; //Address is not a contract. string public constant VL_INVALID_ASSETID_1155 = "118"; //ERC1155 Asset ID is invalid. string public constant VL_NO_ERC1155_BALANCE = "119"; //ERC1155: insufficient balance for transfer. string public constant VL_MISSING_ERC1155_APPROVAL = "120"; //ERC1155: transfer caller is not owner nor approved. string public constant VL_RECEIVER_REJECT_1155 = "121"; //ERC1155Receiver rejected tokens string public constant VL_RECEIVER_CONTRACT_NON_1155 = "122"; //ERC1155: transfer to non ERC1155Receiver implementer string public constant VL_OPTIMIZER_FEE_SMALL = "123"; //Fuji OptimizerFee has to be > 1 RAY (1e27) string public constant VL_UNDERCOLLATERIZED_ERROR = "124"; // Flashloan-Flashclose cannot be used when User's collateral is worth less than intended debt position to close. string public constant VL_MINIMUM_PAYBACK_ERROR = "125"; // Minimum Amount payback should be at least Fuji Optimizerfee accrued interest. string public constant VL_HARVESTING_FAILED = "126"; // Harvesting Function failed, check provided _farmProtocolNum or no claimable balance. string public constant VL_FLASHLOAN_FAILED = "127"; // Flashloan failed string public constant VL_ERC1155_NOT_TRANSFERABLE = "128"; // ERC1155: Not Transferable string public constant VL_SWAP_SLIPPAGE_LIMIT_EXCEED = "129"; // ERC1155: Not Transferable string public constant VL_ZERO_ADDR = "130"; // Zero Address string public constant VL_INVALID_FLASH_NUMBER = "131"; // invalid flashloan number string public constant VL_INVALID_HARVEST_PROTOCOL_NUMBER = "132"; // invalid flashloan number string public constant VL_INVALID_HARVEST_TYPE = "133"; // invalid flashloan number string public constant VL_INVALID_FACTOR = "134"; // invalid factor string public constant VL_INVALID_NEW_PROVIDER ="135"; // invalid newProvider in executeSwitch string public constant MATH_DIVISION_BY_ZERO = "201"; string public constant MATH_ADDITION_OVERFLOW = "202"; string public constant MATH_MULTIPLICATION_OVERFLOW = "203"; string public constant RF_INVALID_RATIO_VALUES = "301"; // Ratio Value provided is invalid, _ratioA/_ratioB <= 1, and > 0, or activeProvider borrowBalance = 0 string public constant RF_INVALID_NEW_ACTIVEPROVIDER = "302"; //Input '_newProvider' and vault's 'activeProvider' must be different string public constant VLT_CALLER_MUST_BE_VAULT = "401"; // The caller of this function must be a vault string public constant ORACLE_INVALID_LENGTH = "501"; // The assets length and price feeds length doesn't match string public constant ORACLE_NONE_PRICE_FEED = "502"; // The price feed is not found }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; library LibUniversalERC20Upgradeable { using SafeERC20Upgradeable for IERC20Upgradeable; IERC20Upgradeable private constant _NATIVE_ADDRESS = IERC20Upgradeable(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); IERC20Upgradeable private constant _ZERO_ADDRESS = IERC20Upgradeable(0x0000000000000000000000000000000000000000); function isNative(IERC20Upgradeable token) internal pure returns (bool) { return (token == _ZERO_ADDRESS || token == _NATIVE_ADDRESS); } function univBalanceOf(IERC20Upgradeable token, address account) internal view returns (uint256) { if (isNative(token)) { return account.balance; } else { return token.balanceOf(account); } } function univTransfer( IERC20Upgradeable token, address payable to, uint256 amount ) internal { if (amount > 0) { if (isNative(token)) { (bool sent, ) = to.call{ value: amount }(""); require(sent, "Failed to send Native"); } else { token.safeTransfer(to, amount); } } } function univApprove( IERC20Upgradeable token, address to, uint256 amount ) internal { require(!isNative(token), "Approve called on Native"); if (amount == 0) { token.safeApprove(to, 0); } else { uint256 allowance = token.allowance(address(this), to); if (allowance < amount) { if (allowance > 0) { token.safeApprove(to, 0); } token.safeApprove(to, amount); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = _setInitializedVersion(1); if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { bool isTopLevelCall = _setInitializedVersion(version); if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(version); } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { _setInitializedVersion(type(uint8).max); } function _setInitializedVersion(uint8 version) private returns (bool) { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level // of initializers, because in other contexts the contract may have been reentered. if (_initializing) { require( version == 1 && !AddressUpgradeable.isContract(address(this)), "Initializable: contract is already initialized" ); return false; } else { require(_initialized < version, "Initializable: contract is already initialized"); _initialized = version; return true; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @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 functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IVaultControl { struct VaultAssets { address collateralAsset; address borrowAsset; uint64 collateralID; uint64 borrowID; } function vAssets() external view returns (VaultAssets memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
{ "optimizer": { "enabled": true, "runs": 500 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userAddrs","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Borrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userAddrs","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newF1155Address","type":"address"}],"name":"F1155Changed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum IVault.FactorType","name":"factorType","type":"uint8"},{"indexed":false,"internalType":"uint64","name":"newFactorA","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newFactorB","type":"uint64"}],"name":"FactorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newFujiAdmin","type":"address"}],"name":"FujiAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOracle","type":"address"}],"name":"OracleChanged","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userAddrs","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Payback","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"newProviderArray","type":"address[]"}],"name":"ProvidersChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newActiveProviderAddress","type":"address"}],"name":"SetActiveProvider","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"fromProviderAddrs","type":"address"},{"indexed":false,"internalType":"address","name":"toProviderAddr","type":"address"},{"indexed":false,"internalType":"uint256","name":"debtamount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collattamount","type":"uint256"}],"name":"Switch","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userAddrs","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"NATIVE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_YEAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeProvider","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bonusLiqF","outputs":[{"internalType":"uint64","name":"a","type":"uint64"},{"internalType":"uint64","name":"b","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_borrowAmount","type":"uint256"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_provider","type":"address"}],"name":"borrowBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collatF","outputs":[{"internalType":"uint64","name":"a","type":"uint64"},{"internalType":"uint64","name":"b","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collateralAmount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collateralAmount","type":"uint256"},{"internalType":"uint256","name":"_borrowAmount","type":"uint256"}],"name":"depositAndBorrow","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_provider","type":"address"}],"name":"depositBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newProvider","type":"address"},{"internalType":"uint256","name":"_flashLoanAmount","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"executeSwitch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"fujiERC1155","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getLiquidationBonusFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_withFactors","type":"bool"}],"name":"getNeededCollateralFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProviders","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_farmProtocolNum","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"harvestRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fujiadmin","type":"address"},{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"address","name":"_collateralAsset","type":"address"},{"internalType":"address","name":"_borrowAsset","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IFujiOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"_repayAmount","type":"int256"}],"name":"payback","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"int256","name":"_paybackAmount","type":"int256"},{"internalType":"int256","name":"_collateralAmount","type":"int256"}],"name":"paybackAndWithdraw","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_users","type":"address[]"},{"internalType":"uint256","name":"_repayAmount","type":"uint256"}],"name":"paybackLiq","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"protocolFee","outputs":[{"internalType":"uint64","name":"a","type":"uint64"},{"internalType":"uint64","name":"b","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"providers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"remainingProtocolFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"safetyF","outputs":[{"internalType":"uint64","name":"a","type":"uint64"},{"internalType":"uint64","name":"b","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_provider","type":"address"}],"name":"setActiveProvider","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_newFactorA","type":"uint64"},{"internalType":"uint64","name":"_newFactorB","type":"uint64"},{"internalType":"enum IVault.FactorType","name":"_type","type":"uint8"}],"name":"setFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newFujiAdmin","type":"address"}],"name":"setFujiAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fujiERC1155","type":"address"}],"name":"setFujiERC1155","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_oracle","type":"address"}],"name":"setOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_providers","type":"address[]"}],"name":"setProviders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateF1155Balances","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"userDebtBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"userDepositBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"userProtocolFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vAssets","outputs":[{"internalType":"address","name":"collateralAsset","type":"address"},{"internalType":"address","name":"borrowAsset","type":"address"},{"internalType":"uint64","name":"collateralID","type":"uint64"},{"internalType":"uint64","name":"borrowID","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"_withdrawAmount","type":"int256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"_withdrawAmount","type":"int256"}],"name":"withdrawLiq","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawProtocolFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040523480156200001157600080fd5b50600062000020600162000087565b9050801562000039576000805461ff0019166101001790555b801562000080576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50620001a8565b60008054610100900460ff161562000120578160ff166001148015620000c05750620000be306200019960201b6200322b1760201c565b155b620001185760405162461bcd60e51b815260206004820152602e60248201526000805160206200581383398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b506000919050565b60005460ff8084169116106200017f5760405162461bcd60e51b815260206004820152602e60248201526000805160206200581383398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016200010f565b506000805460ff191660ff92909216919091179055600190565b6001600160a01b03163b151590565b61565b80620001b86000396000f3fe6080604052600436106102e05760003560e01c80638456cb591161017f578063b0e21e8a116100e1578063df6360a61161008a578063edc922a911610064578063edc922a914610898578063f2fde38b146108ba578063f8c8765e146108da57600080fd5b8063df6360a614610845578063e5aa6d0514610865578063e897effb1461087857600080fd5b8063c5ebeaec116100bb578063c5ebeaec14610797578063cf4f4458146107b7578063d8df4ce7146107ca57600080fd5b8063b0e21e8a14610746578063b6b55f2514610771578063b75061bb1461078457600080fd5b8063956501bb11610143578063a0cf0aea1161011d578063a0cf0aea146106de578063acb2d41014610706578063aef15ac01461072657600080fd5b8063956501bb1461067e57806397f75dd91461069e578063a0add934146106be57600080fd5b80638456cb59146105e05780638b66aceb146105f55780638da5cb5b1461062057806390d7bfae1461063e57806391c154321461065e57600080fd5b806359d8da921161024357806371e11430116101ec5780637dc0d1d0116101c65780637dc0d1d01461058d5780637e62eab8146105ad5780637ec09f9d146105cd57600080fd5b806371e114301461052d5780637adbf9731461054d5780637c802ff21461056d57600080fd5b8063685a46051161021d578063685a4605146104e25780636f1ed6f7146104f8578063715018a61461051857600080fd5b806359d8da92146104955780635c975abb146104aa57806367ac280a146104cd57600080fd5b80631b98f6ac116102a55780634d73e9ba1161027f5780634d73e9ba1461041257806350f3fc81146104325780635564f53d1461046a57600080fd5b80631b98f6ac146103925780631c1fc2cc146103b25780633f4ba83a146103fd57600080fd5b8062197ac7146102ec57806306fdde031461030e57806316d3bfbb146103395780631714decd1461035f57806319e6e4151461037f57600080fd5b366102e757005b600080fd5b3480156102f857600080fd5b5061030c610307366004614f13565b6108fa565b005b34801561031a57600080fd5b50610323610a59565b6040516103309190615302565b60405180910390f35b34801561034557600080fd5b506103516301e1338081565b604051908152602001610330565b34801561036b57600080fd5b5061035161037a366004614c61565b610ae7565b61030c61038d366004614f13565b610bf9565b34801561039e57600080fd5b5061030c6103ad366004614dcf565b610c0d565b3480156103be57600080fd5b5060cd546103dd906001600160401b0380821691600160401b90041682565b604080516001600160401b03938416815292909116602083015201610330565b34801561040957600080fd5b5061030c610ddc565b34801561041e57600080fd5b5061035161042d366004614c61565b610e40565b34801561043e57600080fd5b5061045261044d366004614f13565b610ec6565b6040516001600160a01b039091168152602001610330565b34801561047657600080fd5b5060cc546103dd906001600160401b0380821691600160401b90041682565b3480156104a157600080fd5b5061030c610ef0565b3480156104b657600080fd5b5060655460ff166040519015158152602001610330565b3480156104d957600080fd5b5061030c610fe8565b3480156104ee57600080fd5b5061035160d85481565b34801561050457600080fd5b5061030c610513366004615076565b6111e2565b34801561052457600080fd5b5061030c6116bc565b34801561053957600080fd5b5061030c610548366004614c61565b611720565b34801561055957600080fd5b5061030c610568366004614c61565b6118a1565b34801561057957600080fd5b50610351610588366004614c61565b611a1b565b34801561059957600080fd5b5060d454610452906001600160a01b031681565b3480156105b957600080fd5b5061030c6105c8366004614f13565b611a68565b61030c6105db366004614f2b565b611ad1565b3480156105ec57600080fd5b5061030c611aef565b34801561060157600080fd5b5060cf546103dd906001600160401b0380821691600160401b90041682565b34801561062c57600080fd5b506033546001600160a01b0316610452565b34801561064a57600080fd5b50610351610659366004615047565b611b51565b34801561066a57600080fd5b5061030c610679366004614c61565b611c80565b34801561068a57600080fd5b50610351610699366004614c61565b611d6a565b3480156106aa57600080fd5b5060d154610452906001600160a01b031681565b3480156106ca57600080fd5b5061030c6106d9366004614c61565b611d9e565b3480156106ea57600080fd5b5061045273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b34801561071257600080fd5b5060d354610452906001600160a01b031681565b34801561073257600080fd5b5061030c610741366004615110565b612079565b34801561075257600080fd5b5060ce546103dd906001600160401b0380821691600160401b90041682565b61030c61077f366004614f13565b612468565b61030c610792366004614f2b565b612479565b3480156107a357600080fd5b5061030c6107b2366004614f13565b612493565b61030c6107c5366004614d9b565b6124fc565b3480156107d657600080fd5b5060975460985460995461080b926001600160a01b0390811692908116916001600160401b03600160a01b9092048216911684565b604080516001600160a01b0395861681529490931660208501526001600160401b0391821692840192909252166060820152608001610330565b34801561085157600080fd5b50610351610860366004614c61565b6128c4565b61030c610873366004614e3e565b612968565b34801561088457600080fd5b50610351610893366004614f13565b612c42565b3480156108a457600080fd5b506108ad612c6f565b6040516103309190615257565b3480156108c657600080fd5b5061030c6108d5366004614c61565b612cd1565b3480156108e657600080fd5b5061030c6108f5366004614c99565b612d99565b6002609a5414156109525760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002609a5560d25460408051632e1246a160e21b815290516001600160a01b039092169163b8491a8491600480820192602092909190829003018186803b15801561099c57600080fd5b505afa1580156109b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d49190614c7d565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b81525090610a225760405162461bcd60e51b81526004016109499190615302565b5060d154610a3a9082906001600160a01b031661323a565b609754610a51906001600160a01b03163383613293565b506001609a55565b60d58054610a6690615555565b80601f0160208091040260200160405190810160405280929190818152602001828054610a9290615555565b8015610adf5780601f10610ab457610100808354040283529160200191610adf565b820191906000526020600020905b815481529060010190602001808311610ac257829003601f168201915b505050505081565b60d354609954604051627eeac760e11b81526001600160a01b0384811660048301526001600160401b0390921660248201526000928392169062fdd58e9060440160206040518083038186803b158015610b4057600080fd5b505afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b78919061502f565b60ce546001600160a01b038516600090815260d76020526040812054929350916301e13380916001600160401b03600160401b8204811692911690610bbd9042615512565b610bc790866154f3565b610bd191906154f3565b610bdb91906153e8565b610be591906153e8565b9050610bf181836153d0565b949350505050565b610c01610fe8565b610c0a81613363565b50565b6033546001600160a01b0316331480610cbc575060d260009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c6f57600080fd5b505afa158015610c83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca79190614c7d565b6001600160a01b0316336001600160a01b0316145b6040518060400160405280600381526020016231313160e81b81525090610cf65760405162461bcd60e51b81526004016109499190615302565b5060005b81811015610d91576000838383818110610d2457634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610d399190614c61565b6001600160a01b031614156040518060400160405280600381526020016203133360ec1b81525090610d7e5760405162461bcd60e51b81526004016109499190615302565b5080610d8981615590565b915050610cfa565b50610d9e60d08383614b21565b507f32e7fb34fed79bbb365c7c067731ee80348d07c9bb4a54d399d3c389c2fa9a2f8282604051610dd0929190615209565b60405180910390a15050565b6033546001600160a01b03163314610e365760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610949565b610e3e6136d9565b565b609854604051637d6af07960e01b81526001600160a01b039182166004820152600091831690637d6af079906024015b60206040518083038186803b158015610e8857600080fd5b505afa158015610e9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ec0919061502f565b92915050565b60d08181548110610ed657600080fd5b6000918252602090912001546001600160a01b0316905081565b6002609a541415610f435760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610949565b6002609a5560d25460408051631d8cf42560e11b81529051610fdc926001600160a01b031691633b19e84a916004808301926020929190829003018186803b158015610f8e57600080fd5b505afa158015610fa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc69190614c7d565b60d8546098546001600160a01b03169190613293565b600060d8556001609a55565b60d35460995460d154609854604051637d6af07960e01b81526001600160a01b03918216600482015293811693635eb62f63936001600160401b0316929190911690637d6af0799060240160206040518083038186803b15801561104b57600080fd5b505afa15801561105f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611083919061502f565b6040516001600160e01b031960e085901b1681526001600160401b0390921660048301526024820152604401600060405180830381600087803b1580156110c957600080fd5b505af11580156110dd573d6000803e3d6000fd5b505060d35460985460d154609754604051631da0b5cf60e31b81526001600160a01b0391821660048201529381169550635eb62f639450600160a01b9092046001600160401b03169291169063ed05ae789060240160206040518083038186803b15801561114a57600080fd5b505afa15801561115e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611182919061502f565b6040516001600160e01b031960e085901b1681526001600160401b0390921660048301526024820152604401600060405180830381600087803b1580156111c857600080fd5b505af11580156111dc573d6000803e3d6000fd5b50505050565b6033546001600160a01b0316331461123c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610949565b60008060d260009054906101000a90046001600160a01b03166001600160a01b03166368f1ecc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561128d57600080fd5b505afa1580156112a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c59190614c7d565b6001600160a01b0316635e7361e585856040518363ffffffff1660e01b81526004016112f2929190615360565b600060405180830381600087803b15801561130c57600080fd5b505af1158015611320573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113489190810190614cf4565b91509150600081600001516001600160a01b0316826020015160405161136e91906151aa565b6000604051808303816000865af19150503d80600081146113ab576040519150601f19603f3d011682016040523d82523d6000602084013e6113b0565b606091505b50509050806114015760405162461bcd60e51b815260206004820152601960248201527f6661696c656420746f20686172766573742072657761726473000000000000006044820152606401610949565b6001600160a01b038316156116b55760006114256001600160a01b03851630613775565b90506001600160a01b0384161580159061143f5750600081115b6040518060400160405280600381526020016218991b60e91b815250906114795760405162461bcd60e51b81526004016109499190615302565b5060d254604080516343ad12af60e01b815290516000926001600160a01b0316916343ad12af916004808301926020929190829003018186803b1580156114bf57600080fd5b505afa1580156114d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f79190614c7d565b60975460405163dcab1c0360e01b81526001600160a01b03888116600483015291821660248201526044810185905291169063dcab1c0390606401600060405180830381600087803b15801561154c57600080fd5b505af1158015611560573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115889190810190614f91565b90506001600160a01b03851673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146115c55780516115c5906001600160a01b0387169084613816565b80600001516001600160a01b0316816040015182602001516040516115ea91906151aa565b60006040518083038185875af1925050503d8060008114611627576040519150601f19603f3d011682016040523d82523d6000602084013e61162c565b606091505b5050809350508261167f5760405162461bcd60e51b815260206004820152601660248201527f6661696c656420746f20737761702072657761726473000000000000000000006044820152606401610949565b6097546116aa90611699906001600160a01b031630613775565b60d1546001600160a01b0316613942565b6116b2610fe8565b50505b5050505050565b6033546001600160a01b031633146117165760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610949565b610e3e600061399b565b6033546001600160a01b03163314806117cf575060d260009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561178257600080fd5b505afa158015611796573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117ba9190614c7d565b6001600160a01b0316336001600160a01b0316145b6040518060400160405280600381526020016231313160e81b815250906118095760405162461bcd60e51b81526004016109499190615302565b5060408051808201909152600381526203133360ec1b60208201526001600160a01b03821661184b5760405162461bcd60e51b81526004016109499190615302565b5060d180546001600160a01b0319166001600160a01b0383169081179091556040519081527f623e52a82ff2bab02a51be01f76b0b3178bbafcbe15c455b7ca4c9615b8da598906020015b60405180910390a150565b6033546001600160a01b0316331480611950575060d260009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561190357600080fd5b505afa158015611917573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193b9190614c7d565b6001600160a01b0316336001600160a01b0316145b6040518060400160405280600381526020016231313160e81b8152509061198a5760405162461bcd60e51b81526004016109499190615302565b5060408051808201909152600381526203133360ec1b60208201526001600160a01b0382166119cc5760405162461bcd60e51b81526004016109499190615302565b5060d480546001600160a01b0319166001600160a01b0383169081179091556040519081527f0e05ae75e8b926552cf6fcd744d19f422561e3ced1e426868730852702dbe41890602001611896565b60d354609854604051627eeac760e11b81526001600160a01b038481166004830152600160a01b9092046001600160401b03166024820152600092919091169062fdd58e90604401610e70565b6002609a541415611abb5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610949565b6002609a55611ac8610fe8565b610a51816139ed565b611ad9610fe8565b611ae282613363565b611aeb816139ed565b5050565b6033546001600160a01b03163314611b495760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610949565b610e3e613d01565b60d45460975460985460d65460405163721adea760e01b81526001600160a01b039384166004820152918316602483015260ff1660448201526000928392169063721adea79060640160206040518083038186803b158015611bb257600080fd5b505afa158015611bc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bea919061502f565b60d654909150600090611c0690610100900460ff16600a61544b565b611c1083876154f3565b611c1a91906153e8565b90508315611c775760cc5460cd546001600160401b03600160401b80840482169390830482169290821691611c509116856154f3565b611c5a91906154f3565b611c6491906153e8565b611c6e91906153e8565b92505050610ec0565b9150610ec09050565b6033546001600160a01b03163314611cda5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610949565b60408051808201909152600381526203133360ec1b60208201526001600160a01b038216611d1b5760405162461bcd60e51b81526004016109499190615302565b5060d280546001600160a01b0319166001600160a01b0383169081179091556040519081527fa05e64ea7e34b372177317c71229808e25bdbfe5dc3e6bc4fc7ca66c97d9327690602001611896565b609754604051631da0b5cf60e31b81526001600160a01b03918216600482015260009183169063ed05ae7890602401610e70565b6033546001600160a01b0316331480611e4d575060d260009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b158015611e0057600080fd5b505afa158015611e14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e389190614c7d565b6001600160a01b0316336001600160a01b0316145b6040518060400160405280600381526020016231313160e81b81525090611e875760405162461bcd60e51b81526004016109499190615302565b5060408051808201909152600381526203133360ec1b60208201526001600160a01b038216611ec95760405162461bcd60e51b81526004016109499190615302565b5060d380546001600160a01b0319166001600160a01b0383169081179091556040516330e2d1ed60e01b81526330e2d1ed90611f0c9060009030906004016152a4565b602060405180830381600087803b158015611f2657600080fd5b505af1158015611f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5e91906150f4565b609880546001600160401b0392909216600160a01b027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff9092169190911790556040516330e2d1ed60e01b81526001600160a01b038216906330e2d1ed90611fcd9060019030906004016152a4565b602060405180830381600087803b158015611fe757600080fd5b505af1158015611ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201f91906150f4565b6099805467ffffffffffffffff19166001600160401b03929092169190911790556040516001600160a01b03821681527fb89c4162816fee2afc84abac7e339928e379cd5d1d61acadaa52a39ce2650b6b90602001611896565b6033546001600160a01b0316331480612128575060d260009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156120db57600080fd5b505afa1580156120ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121139190614c7d565b6001600160a01b0316336001600160a01b0316145b6040518060400160405280600381526020016231313160e81b815250906121625760405162461bcd60e51b81526004016109499190615302565b50600081600381111561218557634e487b7160e01b600052602160045260246000fd5b141561220857816001600160401b0316836001600160401b0316116040518060400160405280600381526020016233303160e81b815250906121da5760405162461bcd60e51b81526004016109499190615302565b5060cc80546001600160401b03848116600160401b026001600160801b031990921690861617179055612428565b600181600381111561222a57634e487b7160e01b600052602160045260246000fd5b14156122ad57816001600160401b0316836001600160401b0316116040518060400160405280600381526020016233303160e81b8152509061227f5760405162461bcd60e51b81526004016109499190615302565b5060cd80546001600160401b03848116600160401b026001600160801b031990921690861617179055612428565b60028160038111156122cf57634e487b7160e01b600052602160045260246000fd5b141561235257816001600160401b0316836001600160401b0316106040518060400160405280600381526020016233303160e81b815250906123245760405162461bcd60e51b81526004016109499190615302565b5060ce80546001600160401b03848116600160401b026001600160801b031990921690861617179055612428565b600381600381111561237457634e487b7160e01b600052602160045260246000fd5b14156123f757816001600160401b0316836001600160401b0316106040518060400160405280600381526020016233303160e81b815250906123c95760405162461bcd60e51b81526004016109499190615302565b5060cf80546001600160401b03848116600160401b026001600160801b031990921690861617179055612428565b60408051808201825260038152620c4ccd60ea1b6020820152905162461bcd60e51b81526109499190600401615302565b7f684344b55402a828ac72dba82a6cdde8094ee32955d4c34d290d43d1a703612281848460405161245b939291906152d0565b60405180910390a1505050565b612470610fe8565b610c0a81613d7c565b612481610fe8565b61248a82613d7c565b611aeb81613f1d565b6002609a5414156124e65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610949565b6002609a556124f3610fe8565b610a5181613f1d565b60d260009054906101000a90046001600160a01b03166001600160a01b0316637fabc90b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561254a57600080fd5b505afa15801561255e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125829190614c7d565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b815250906125d05760405162461bcd60e51b81526004016109499190615302565b5060655460ff16156126175760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610949565b6000805b60d05481101561267c5760d0818154811061264657634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b038681169116141561266a57600191505b8061267481615590565b91505061261b565b50806126b357604080518082018252600381526231333560e81b6020820152905162461bcd60e51b81526109499190600401615302565b60d154609854604051637d6af07960e01b81526001600160a01b0391821660048201526000929190911690637d6af0799060240160206040518083038186803b1580156126ff57600080fd5b505afa158015612713573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612737919061502f565b61274985670de0b6b3a76400006154f3565b61275391906153e8565b60d15490915061276d9085906001600160a01b03166142b2565b60d154609754604051631da0b5cf60e31b81526001600160a01b039182166004820152600092670de0b6b3a764000092859291169063ed05ae789060240160206040518083038186803b1580156127c357600080fd5b505afa1580156127d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127fb919061502f565b61280591906154f3565b61280f91906153e8565b60d1549091506128299082906001600160a01b031661323a565b6128338187613942565b61284661284085876153d0565b8761430b565b6128673361285486886153d0565b6098546001600160a01b03169190613293565b60d154604080516001600160a01b03928316815291881660208301528101869052606081018290527f06792f8797628d4ae9a2a9ec4ff047ef0d1f3fca2c413ec76165fd8c5b125bd99060800160405180910390a1505050505050565b60d354609954604051627eeac760e11b81526001600160a01b0384811660048301526001600160401b0390921660248201526000928392169062fdd58e9060440160206040518083038186803b15801561291d57600080fd5b505afa158015612931573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612955919061502f565b90506129618382614364565b9392505050565b60d260009054906101000a90046001600160a01b03166001600160a01b031663b8491a846040518163ffffffff1660e01b815260040160206040518083038186803b1580156129b657600080fd5b505afa1580156129ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ee9190614c7d565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b81525090612a3c5760405162461bcd60e51b81526004016109499190615302565b506000805b8351811015612c075760006001600160a01b0316848281518110612a7557634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031614612bf5574260d76000868481518110612ab057634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002081905550600060d360009054906101000a90046001600160a01b03166001600160a01b031662fdd58e868481518110612b2157634e487b7160e01b600052603260045260246000fd5b602090810291909101015160995460405160e084901b6001600160e01b03191681526001600160a01b0390921660048301526001600160401b0316602482015260440160206040518083038186803b158015612b7c57600080fd5b505afa158015612b90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bb4919061502f565b9050612be7858381518110612bd957634e487b7160e01b600052603260045260246000fd5b602002602001015182614364565b612bf190846153d0565b9250505b80612bff81615590565b915050612a41565b50612c26612c158284615512565b60d1546001600160a01b03166142b2565b8060d86000828254612c3891906153d0565b9091555050505050565b60cf546000906001600160401b03600160401b8204811691612c659116846154f3565b610ec091906153e8565b606060d0805480602002602001604051908101604052809291908181526020018280548015612cc757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612ca9575b5050505050905090565b6033546001600160a01b03163314612d2b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610949565b6001600160a01b038116612d905760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610949565b610c0a8161399b565b6000612da560016143ce565b90508015612dbd576000805461ff0019166101001790555b6001600160a01b03851615801590612ddd57506001600160a01b03841615155b8015612df157506001600160a01b03831615155b8015612e0557506001600160a01b03821615155b6040518060400160405280600381526020016203133360ec1b81525090612e3f5760405162461bcd60e51b81526004016109499190615302565b50612e486144e4565b612e50614513565b612e58614542565b60d280546001600160a01b038088166001600160a01b03199283161790925560d480548784169083161790556097805486841690831681179091556098805493861693909216929092179055606090819073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415612ef5576040805180820190915260068152654e415449564560d01b602082015260d6805460ff191660121790559150612ff2565b846001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b158015612f2e57600080fd5b505afa158015612f42573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612f6a9190810190614f4c565b9150846001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612fa557600080fd5b505afa158015612fb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fdd919061515d565b60d6805460ff191660ff929092169190911790555b6001600160a01b03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561304957506040805180820190915260068152654e415449564560d01b602082015260d6805461ff00191661120017905561314c565b836001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801561308257600080fd5b505afa158015613096573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526130be9190810190614f4c565b9050836001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156130f957600080fd5b505afa15801561310d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613131919061515d565b60d660016101000a81548160ff021916908360ff1602179055505b818160405160200161315f9291906151c6565b60405160208183030381529060405260d59080519060200190613183929190614b84565b505060cc80546001600160801b0319908116681400000000000000151790915560cd80548216683f000000000000005017905560cf805482166814000000000000000117905560ce80549091166903e800000000000000011790555080156116b5576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6001600160a01b03163b151590565b6097546040516001600160a01b0390911660248201526044810183905260009060640160408051601f198184030181529190526020810180516001600160e01b031663f3fef3a360e01b17905290506111dc8282614571565b801561335e576132a2836146ab565b1561334a576000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146132f4576040519150601f19603f3d011682016040523d82523d6000602084013e6132f9565b606091505b50509050806111dc5760405162461bcd60e51b815260206004820152601560248201527f4661696c656420746f2073656e64204e617469766500000000000000000000006044820152606401610949565b61335e6001600160a01b03841683836146e4565b505050565b60d354609954604051627eeac760e11b81523360048201526001600160401b0390911660248201526000916001600160a01b03169062fdd58e9060440160206040518083038186803b1580156133b857600080fd5b505afa1580156133cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133f0919061502f565b905060006133fe3383614364565b9050808311801561340f5750600082115b6040518060400160405280600381526020016218981b60e91b815250906134495760405162461bcd60e51b81526004016109499190615302565b5060008084126134595783613463565b61346382846153d0565b6098549091506001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156134e757803410156040518060400160405280600381526020016231303360e81b815250906134cb5760405162461bcd60e51b81526004016109499190615302565b50803411156134e2576134e2336128548334615512565b6135bd565b609854604051636eb1769f60e11b815233600482015230602482015282916001600160a01b03169063dd62ed3e9060440160206040518083038186803b15801561353057600080fd5b505afa158015613544573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613568919061502f565b10156040518060400160405280600381526020016231303760e81b815250906135a45760405162461bcd60e51b81526004016109499190615302565b506098546135bd906001600160a01b0316333084614747565b6135ca612c158383615512565b60d3546099546001600160a01b039091169063f5298aca9033906001600160401b03166135f78686615512565b6040516001600160e01b031960e086901b1681526001600160a01b0390931660048401526001600160401b0390911660248301526044820152606401600060405180830381600087803b15801561364d57600080fd5b505af1158015613661573d6000803e3d6000fd5b505033600090815260d76020526040812042905560d8805486945090925061368a9084906153d0565b90915550506098546040518281526001600160a01b039091169033907ffc2d2b4b3ad857c1c0893799f86b421efff822709b26de93df5709671f4841ca9060200160405180910390a350505050565b60655460ff1661372b5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610949565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6000613780836146ab565b1561379657506001600160a01b03811631610ec0565b6040516370a0823160e01b81526001600160a01b0383811660048301528416906370a082319060240160206040518083038186803b1580156137d757600080fd5b505afa1580156137eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061380f919061502f565b9050610ec0565b61381f836146ab565b1561386c5760405162461bcd60e51b815260206004820152601860248201527f417070726f76652063616c6c6564206f6e204e617469766500000000000000006044820152606401610949565b806138865761335e6001600160a01b03841683600061477f565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e9060440160206040518083038186803b1580156138d157600080fd5b505afa1580156138e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613909919061502f565b9050818110156111dc57801561392e5761392e6001600160a01b03851684600061477f565b6111dc6001600160a01b038516848461477f565b6097546040516001600160a01b0390911660248201526044810183905260009060640160408051601f198184030181529190526020810180516001600160e01b03166311f9fbc960e21b17905290506111dc8282614571565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60d354609854604051627eeac760e11b8152336004820152600160a01b9091046001600160401b031660248201526000916001600160a01b03169062fdd58e9060440160206040518083038186803b158015613a4857600080fd5b505afa158015613a5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a80919061502f565b9050600081116040518060400160405280600381526020016218989960e91b81525090613ac05760405162461bcd60e51b81526004016109499190615302565b5060d354609954604051627eeac760e11b81523360048201526001600160401b039091166024820152600091613b5b916001600160a01b039091169062fdd58e9060440160206040518083038186803b158015613b1c57600080fd5b505afa158015613b30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b54919061502f565b6001611b51565b90506000808412613b6c5783613b76565b613b768284615512565b90508015801590613b90575081613b8d8285615512565b10155b604051806040016040528060038152602001620c4c0d60ea1b81525090613bca5760405162461bcd60e51b81526004016109499190615302565b50609754600090613be4906001600160a01b031630613775565b60d154909150613bfe9083906001600160a01b031661323a565b6097548190613c16906001600160a01b031630613775565b613c209190615512565b60d354609854604051637a94c56560e11b8152336004820152600160a01b9091046001600160401b03166024820152604481018390529193506001600160a01b03169063f5298aca90606401600060405180830381600087803b158015613c8657600080fd5b505af1158015613c9a573d6000803e3d6000fd5b5050609754613cb692506001600160a01b031690503384613293565b6097546040518381526001600160a01b039091169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb9060200160405180910390a35050505050565b60655460ff1615613d475760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610949565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586137583390565b6097546001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613df1578034148015613db157508015155b6040518060400160405280600381526020016231303360e81b81525090613deb5760405162461bcd60e51b81526004016109499190615302565b50613e42565b60408051808201909152600381526231303360e81b602082015281613e295760405162461bcd60e51b81526004016109499190615302565b50609754613e42906001600160a01b0316333084614747565b60d154613e599082906001600160a01b0316613942565b60d354609854604051630ab714fb60e11b8152336004820152600160a01b9091046001600160401b03166024820152604481018390526001600160a01b039091169063156e29f690606401600060405180830381600087803b158015613ebe57600080fd5b505af1158015613ed2573d6000803e3d6000fd5b50506097546040518481526001600160a01b0390911692503391507f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f629060200160405180910390a350565b60d354609854604051627eeac760e11b8152336004820152600160a01b9091046001600160401b031660248201526000916001600160a01b03169062fdd58e9060440160206040518083038186803b158015613f7857600080fd5b505afa158015613f8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fb0919061502f565b60d354609954604051627eeac760e11b81523360048201526001600160401b0390911660248201529192506000916001600160a01b039091169062fdd58e9060440160206040518083038186803b15801561400a57600080fd5b505afa15801561401e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614042919061502f565b9050600061405082856153d0565b9050600061405f826001611b51565b9050841580159061406f57508084115b6040518060400160405280600381526020016231303560e81b815250906140a95760405162461bcd60e51b81526004016109499190615302565b506098546000906140c3906001600160a01b031630613775565b60d1549091506140dd9087906001600160a01b031661430b565b60985481906140f5906001600160a01b031630613775565b6140ff9190615512565b955061410b84876153d0565b60ce5433600090815260d76020526040812054929550916301e13380916001600160401b03600160401b82048116929116906141479042615512565b61415190896154f3565b61415b91906154f3565b61416591906153e8565b61416f91906153e8565b60ce5490915084906001600160401b03600160401b8204811691166141986301e13380856154f3565b6141a291906154f3565b6141ac91906153e8565b6141b691906153e8565b6141c09042615512565b33600081815260d76020526040908190209290925560d3546099549251630ab714fb60e11b815260048101929092526001600160401b039092166024820152604481018990526001600160a01b039091169063156e29f690606401600060405180830381600087803b15801561423557600080fd5b505af1158015614249573d6000803e3d6000fd5b505060985461426592506001600160a01b031690503389613293565b6098546040518881526001600160a01b039091169033907f312a5e5e1079f5dda4e95dbbd0b908b291fd5b992ef22073643ab691572c5b529060200160405180910390a350505050505050565b6098546040516001600160a01b0390911660248201526044810183905260009060640160408051601f198184030181529190526020810180516001600160e01b03166306bdb15760e31b17905290506111dc8282614571565b6098546040516001600160a01b0390911660248201526044810183905260009060640160408051601f198184030181529190526020810180516001600160e01b0316634b8a352960e01b17905290506111dc8282614571565b60ce546001600160a01b038316600090815260d7602052604081205490916301e13380916001600160401b03600160401b830481169216906143a69042615512565b6143b090866154f3565b6143ba91906154f3565b6143c491906153e8565b61296191906153e8565b60008054610100900460ff161561445c578160ff1660011480156143f15750303b155b6144545760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610949565b506000919050565b60005460ff8084169116106144ca5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610949565b506000805460ff191660ff92909216919091179055600190565b600054610100900460ff1661450b5760405162461bcd60e51b815260040161094990615315565b610e3e6148aa565b600054610100900460ff1661453a5760405162461bcd60e51b815260040161094990615315565b610e3e6148da565b600054610100900460ff166145695760405162461bcd60e51b815260040161094990615315565b610e3e61490d565b606061457f60655460ff1690565b156145bf5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610949565b60408051808201909152600381526231313760e81b60208201526001600160a01b0384163b6146015760405162461bcd60e51b81526004016109499190615302565b50600080846001600160a01b03168460405161461d91906151aa565b600060405180830381855af49150503d8060008114614658576040519150601f19603f3d011682016040523d82523d6000602084013e61465d565b606091505b50915091506146a282826040518060400160405280602081526020017f64656c65676174652063616c6c20746f2070726f7669646572206661696c656481525061493b565b95945050505050565b60006001600160a01b0382161580610ec057506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b6040516001600160a01b03831660248201526044810182905261335e90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614974565b6040516001600160a01b03808516602483015283166044820152606481018290526111dc9085906323b872dd60e01b90608401614710565b8015806148085750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156147ce57600080fd5b505afa1580156147e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614806919061502f565b155b61487a5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610949565b6040516001600160a01b03831660248201526044810182905261335e90849063095ea7b360e01b90606401614710565b600054610100900460ff166148d15760405162461bcd60e51b815260040161094990615315565b610e3e3361399b565b600054610100900460ff166149015760405162461bcd60e51b815260040161094990615315565b6065805460ff19169055565b600054610100900460ff166149345760405162461bcd60e51b815260040161094990615315565b6001609a55565b6060831561494a575081612961565b82511561495a5782518084602001fd5b8160405162461bcd60e51b81526004016109499190615302565b60006149c9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614a469092919063ffffffff16565b80519091501561335e57808060200190518101906149e79190614ef7565b61335e5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610949565b6060610bf18484600085856001600160a01b0385163b614aa85760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610949565b600080866001600160a01b03168587604051614ac491906151aa565b60006040518083038185875af1925050503d8060008114614b01576040519150601f19603f3d011682016040523d82523d6000602084013e614b06565b606091505b5091509150614b1682828661493b565b979650505050505050565b828054828255906000526020600020908101928215614b74579160200282015b82811115614b745781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190614b41565b50614b80929150614bf8565b5090565b828054614b9090615555565b90600052602060002090601f016020900481019282614bb25760008555614b74565b82601f10614bcb57805160ff1916838001178555614b74565b82800160010185558215614b74579182015b82811115614b74578251825591602001919060010190614bdd565b5b80821115614b805760008155600101614bf9565b6000614c20614c1b846153a9565b615379565b9050828152838383011115614c3457600080fd5b612961836020830184615529565b600082601f830112614c52578081fd5b61296183835160208501614c0d565b600060208284031215614c72578081fd5b8135612961816155ed565b600060208284031215614c8e578081fd5b8151612961816155ed565b60008060008060808587031215614cae578283fd5b8435614cb9816155ed565b93506020850135614cc9816155ed565b92506040850135614cd9816155ed565b91506060850135614ce9816155ed565b939692955090935050565b60008060408385031215614d06578081fd5b8251614d11816155ed565b60208401519092506001600160401b0380821115614d2d578283fd5b9084019060408287031215614d40578283fd5b604051604081018181108382111715614d5b57614d5b6155d7565b6040528251614d69816155ed565b8152602083015182811115614d7c578485fd5b614d8888828601614c42565b6020830152508093505050509250929050565b600080600060608486031215614daf578081fd5b8335614dba816155ed565b95602085013595506040909401359392505050565b60008060208385031215614de1578182fd5b82356001600160401b0380821115614df7578384fd5b818501915085601f830112614e0a578384fd5b813581811115614e18578485fd5b8660208260051b8501011115614e2c578485fd5b60209290920196919550909350505050565b60008060408385031215614e50578182fd5b82356001600160401b0380821115614e66578384fd5b818501915085601f830112614e79578384fd5b8135602082821115614e8d57614e8d6155d7565b8160051b9250614e9e818401615379565b8281528181019085830185870184018b1015614eb8578889fd5b8896505b84871015614ee65780359550614ed1866155ed565b85835260019690960195918301918301614ebc565b509997909101359750505050505050565b600060208284031215614f08578081fd5b815161296181615602565b600060208284031215614f24578081fd5b5035919050565b60008060408385031215614f3d578182fd5b50508035926020909101359150565b600060208284031215614f5d578081fd5b81516001600160401b03811115614f72578182fd5b8201601f81018413614f82578182fd5b610bf184825160208401614c0d565b600060208284031215614fa2578081fd5b81516001600160401b0380821115614fb8578283fd5b9083019060608286031215614fcb578283fd5b604051606081018181108382111715614fe657614fe66155d7565b6040528251614ff4816155ed565b8152602083015182811115615007578485fd5b61501387828601614c42565b6020830152506040830151604082015280935050505092915050565b600060208284031215615040578081fd5b5051919050565b60008060408385031215615059578182fd5b82359150602083013561506b81615602565b809150509250929050565b60008060408385031215615088578182fd5b8235915060208301356001600160401b038111156150a4578182fd5b8301601f810185136150b4578182fd5b80356150c2614c1b826153a9565b8181528660208385010111156150d6578384fd5b81602084016020830137908101602001929092525090939092509050565b600060208284031215615105578081fd5b815161296181615610565b600080600060608486031215615124578081fd5b833561512f81615610565b9250602084013561513f81615610565b9150604084013560048110615152578182fd5b809150509250925092565b60006020828403121561516e578081fd5b815160ff81168114612961578182fd5b60008151808452615196816020860160208601615529565b601f01601f19169290920160200192915050565b600082516151bc818460208701615529565b9190910192915050565b6415985d5b1d60da1b8152600083516151e6816005850160208801615529565b8351908301906151fd816005840160208801615529565b01600501949350505050565b60208082528181018390526000908460408401835b8681101561524c578235615231816155ed565b6001600160a01b03168252918301919083019060010161521e565b509695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156152985783516001600160a01b031683529284019291840191600101615273565b50909695505050505050565b60408101600284106152b8576152b86155c1565b9281526001600160a01b039190911660209091015290565b60608101600485106152e4576152e46155c1565b9381526001600160401b039283166020820152911660409091015290565b602081526000612961602083018461517e565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b828152604060208201526000610bf1604083018461517e565b604051601f8201601f191681016001600160401b03811182821017156153a1576153a16155d7565b604052919050565b60006001600160401b038211156153c2576153c26155d7565b50601f01601f191660200190565b600082198211156153e3576153e36155ab565b500190565b60008261540357634e487b7160e01b81526012600452602481fd5b500490565b600181815b80851115615443578160001904821115615429576154296155ab565b8085161561543657918102915b93841c939080029061540d565b509250929050565b6000612961838360008261546157506001610ec0565b8161546e57506000610ec0565b8160018114615484576002811461548e576154aa565b6001915050610ec0565b60ff84111561549f5761549f6155ab565b50506001821b610ec0565b5060208310610133831016604e8410600b84101617156154cd575081810a610ec0565b6154d78383615408565b80600019048211156154eb576154eb6155ab565b029392505050565b600081600019048311821515161561550d5761550d6155ab565b500290565b600082821015615524576155246155ab565b500390565b60005b8381101561554457818101518382015260200161552c565b838111156111dc5750506000910152565b600181811c9082168061556957607f821691505b6020821081141561558a57634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156155a4576155a46155ab565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610c0a57600080fd5b8015158114610c0a57600080fd5b6001600160401b0381168114610c0a57600080fdfea2646970667358221220c953783e362a54ecad874fb7007b23fa77c79f535731e3c45a9717a189aadc8964736f6c63430008040033496e697469616c697a61626c653a20636f6e747261637420697320616c726561
Deployed Bytecode
0x6080604052600436106102e05760003560e01c80638456cb591161017f578063b0e21e8a116100e1578063df6360a61161008a578063edc922a911610064578063edc922a914610898578063f2fde38b146108ba578063f8c8765e146108da57600080fd5b8063df6360a614610845578063e5aa6d0514610865578063e897effb1461087857600080fd5b8063c5ebeaec116100bb578063c5ebeaec14610797578063cf4f4458146107b7578063d8df4ce7146107ca57600080fd5b8063b0e21e8a14610746578063b6b55f2514610771578063b75061bb1461078457600080fd5b8063956501bb11610143578063a0cf0aea1161011d578063a0cf0aea146106de578063acb2d41014610706578063aef15ac01461072657600080fd5b8063956501bb1461067e57806397f75dd91461069e578063a0add934146106be57600080fd5b80638456cb59146105e05780638b66aceb146105f55780638da5cb5b1461062057806390d7bfae1461063e57806391c154321461065e57600080fd5b806359d8da921161024357806371e11430116101ec5780637dc0d1d0116101c65780637dc0d1d01461058d5780637e62eab8146105ad5780637ec09f9d146105cd57600080fd5b806371e114301461052d5780637adbf9731461054d5780637c802ff21461056d57600080fd5b8063685a46051161021d578063685a4605146104e25780636f1ed6f7146104f8578063715018a61461051857600080fd5b806359d8da92146104955780635c975abb146104aa57806367ac280a146104cd57600080fd5b80631b98f6ac116102a55780634d73e9ba1161027f5780634d73e9ba1461041257806350f3fc81146104325780635564f53d1461046a57600080fd5b80631b98f6ac146103925780631c1fc2cc146103b25780633f4ba83a146103fd57600080fd5b8062197ac7146102ec57806306fdde031461030e57806316d3bfbb146103395780631714decd1461035f57806319e6e4151461037f57600080fd5b366102e757005b600080fd5b3480156102f857600080fd5b5061030c610307366004614f13565b6108fa565b005b34801561031a57600080fd5b50610323610a59565b6040516103309190615302565b60405180910390f35b34801561034557600080fd5b506103516301e1338081565b604051908152602001610330565b34801561036b57600080fd5b5061035161037a366004614c61565b610ae7565b61030c61038d366004614f13565b610bf9565b34801561039e57600080fd5b5061030c6103ad366004614dcf565b610c0d565b3480156103be57600080fd5b5060cd546103dd906001600160401b0380821691600160401b90041682565b604080516001600160401b03938416815292909116602083015201610330565b34801561040957600080fd5b5061030c610ddc565b34801561041e57600080fd5b5061035161042d366004614c61565b610e40565b34801561043e57600080fd5b5061045261044d366004614f13565b610ec6565b6040516001600160a01b039091168152602001610330565b34801561047657600080fd5b5060cc546103dd906001600160401b0380821691600160401b90041682565b3480156104a157600080fd5b5061030c610ef0565b3480156104b657600080fd5b5060655460ff166040519015158152602001610330565b3480156104d957600080fd5b5061030c610fe8565b3480156104ee57600080fd5b5061035160d85481565b34801561050457600080fd5b5061030c610513366004615076565b6111e2565b34801561052457600080fd5b5061030c6116bc565b34801561053957600080fd5b5061030c610548366004614c61565b611720565b34801561055957600080fd5b5061030c610568366004614c61565b6118a1565b34801561057957600080fd5b50610351610588366004614c61565b611a1b565b34801561059957600080fd5b5060d454610452906001600160a01b031681565b3480156105b957600080fd5b5061030c6105c8366004614f13565b611a68565b61030c6105db366004614f2b565b611ad1565b3480156105ec57600080fd5b5061030c611aef565b34801561060157600080fd5b5060cf546103dd906001600160401b0380821691600160401b90041682565b34801561062c57600080fd5b506033546001600160a01b0316610452565b34801561064a57600080fd5b50610351610659366004615047565b611b51565b34801561066a57600080fd5b5061030c610679366004614c61565b611c80565b34801561068a57600080fd5b50610351610699366004614c61565b611d6a565b3480156106aa57600080fd5b5060d154610452906001600160a01b031681565b3480156106ca57600080fd5b5061030c6106d9366004614c61565b611d9e565b3480156106ea57600080fd5b5061045273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b34801561071257600080fd5b5060d354610452906001600160a01b031681565b34801561073257600080fd5b5061030c610741366004615110565b612079565b34801561075257600080fd5b5060ce546103dd906001600160401b0380821691600160401b90041682565b61030c61077f366004614f13565b612468565b61030c610792366004614f2b565b612479565b3480156107a357600080fd5b5061030c6107b2366004614f13565b612493565b61030c6107c5366004614d9b565b6124fc565b3480156107d657600080fd5b5060975460985460995461080b926001600160a01b0390811692908116916001600160401b03600160a01b9092048216911684565b604080516001600160a01b0395861681529490931660208501526001600160401b0391821692840192909252166060820152608001610330565b34801561085157600080fd5b50610351610860366004614c61565b6128c4565b61030c610873366004614e3e565b612968565b34801561088457600080fd5b50610351610893366004614f13565b612c42565b3480156108a457600080fd5b506108ad612c6f565b6040516103309190615257565b3480156108c657600080fd5b5061030c6108d5366004614c61565b612cd1565b3480156108e657600080fd5b5061030c6108f5366004614c99565b612d99565b6002609a5414156109525760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b6002609a5560d25460408051632e1246a160e21b815290516001600160a01b039092169163b8491a8491600480820192602092909190829003018186803b15801561099c57600080fd5b505afa1580156109b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d49190614c7d565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b81525090610a225760405162461bcd60e51b81526004016109499190615302565b5060d154610a3a9082906001600160a01b031661323a565b609754610a51906001600160a01b03163383613293565b506001609a55565b60d58054610a6690615555565b80601f0160208091040260200160405190810160405280929190818152602001828054610a9290615555565b8015610adf5780601f10610ab457610100808354040283529160200191610adf565b820191906000526020600020905b815481529060010190602001808311610ac257829003601f168201915b505050505081565b60d354609954604051627eeac760e11b81526001600160a01b0384811660048301526001600160401b0390921660248201526000928392169062fdd58e9060440160206040518083038186803b158015610b4057600080fd5b505afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b78919061502f565b60ce546001600160a01b038516600090815260d76020526040812054929350916301e13380916001600160401b03600160401b8204811692911690610bbd9042615512565b610bc790866154f3565b610bd191906154f3565b610bdb91906153e8565b610be591906153e8565b9050610bf181836153d0565b949350505050565b610c01610fe8565b610c0a81613363565b50565b6033546001600160a01b0316331480610cbc575060d260009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c6f57600080fd5b505afa158015610c83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca79190614c7d565b6001600160a01b0316336001600160a01b0316145b6040518060400160405280600381526020016231313160e81b81525090610cf65760405162461bcd60e51b81526004016109499190615302565b5060005b81811015610d91576000838383818110610d2457634e487b7160e01b600052603260045260246000fd5b9050602002016020810190610d399190614c61565b6001600160a01b031614156040518060400160405280600381526020016203133360ec1b81525090610d7e5760405162461bcd60e51b81526004016109499190615302565b5080610d8981615590565b915050610cfa565b50610d9e60d08383614b21565b507f32e7fb34fed79bbb365c7c067731ee80348d07c9bb4a54d399d3c389c2fa9a2f8282604051610dd0929190615209565b60405180910390a15050565b6033546001600160a01b03163314610e365760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610949565b610e3e6136d9565b565b609854604051637d6af07960e01b81526001600160a01b039182166004820152600091831690637d6af079906024015b60206040518083038186803b158015610e8857600080fd5b505afa158015610e9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ec0919061502f565b92915050565b60d08181548110610ed657600080fd5b6000918252602090912001546001600160a01b0316905081565b6002609a541415610f435760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610949565b6002609a5560d25460408051631d8cf42560e11b81529051610fdc926001600160a01b031691633b19e84a916004808301926020929190829003018186803b158015610f8e57600080fd5b505afa158015610fa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc69190614c7d565b60d8546098546001600160a01b03169190613293565b600060d8556001609a55565b60d35460995460d154609854604051637d6af07960e01b81526001600160a01b03918216600482015293811693635eb62f63936001600160401b0316929190911690637d6af0799060240160206040518083038186803b15801561104b57600080fd5b505afa15801561105f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611083919061502f565b6040516001600160e01b031960e085901b1681526001600160401b0390921660048301526024820152604401600060405180830381600087803b1580156110c957600080fd5b505af11580156110dd573d6000803e3d6000fd5b505060d35460985460d154609754604051631da0b5cf60e31b81526001600160a01b0391821660048201529381169550635eb62f639450600160a01b9092046001600160401b03169291169063ed05ae789060240160206040518083038186803b15801561114a57600080fd5b505afa15801561115e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611182919061502f565b6040516001600160e01b031960e085901b1681526001600160401b0390921660048301526024820152604401600060405180830381600087803b1580156111c857600080fd5b505af11580156111dc573d6000803e3d6000fd5b50505050565b6033546001600160a01b0316331461123c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610949565b60008060d260009054906101000a90046001600160a01b03166001600160a01b03166368f1ecc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561128d57600080fd5b505afa1580156112a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c59190614c7d565b6001600160a01b0316635e7361e585856040518363ffffffff1660e01b81526004016112f2929190615360565b600060405180830381600087803b15801561130c57600080fd5b505af1158015611320573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113489190810190614cf4565b91509150600081600001516001600160a01b0316826020015160405161136e91906151aa565b6000604051808303816000865af19150503d80600081146113ab576040519150601f19603f3d011682016040523d82523d6000602084013e6113b0565b606091505b50509050806114015760405162461bcd60e51b815260206004820152601960248201527f6661696c656420746f20686172766573742072657761726473000000000000006044820152606401610949565b6001600160a01b038316156116b55760006114256001600160a01b03851630613775565b90506001600160a01b0384161580159061143f5750600081115b6040518060400160405280600381526020016218991b60e91b815250906114795760405162461bcd60e51b81526004016109499190615302565b5060d254604080516343ad12af60e01b815290516000926001600160a01b0316916343ad12af916004808301926020929190829003018186803b1580156114bf57600080fd5b505afa1580156114d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f79190614c7d565b60975460405163dcab1c0360e01b81526001600160a01b03888116600483015291821660248201526044810185905291169063dcab1c0390606401600060405180830381600087803b15801561154c57600080fd5b505af1158015611560573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115889190810190614f91565b90506001600160a01b03851673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146115c55780516115c5906001600160a01b0387169084613816565b80600001516001600160a01b0316816040015182602001516040516115ea91906151aa565b60006040518083038185875af1925050503d8060008114611627576040519150601f19603f3d011682016040523d82523d6000602084013e61162c565b606091505b5050809350508261167f5760405162461bcd60e51b815260206004820152601660248201527f6661696c656420746f20737761702072657761726473000000000000000000006044820152606401610949565b6097546116aa90611699906001600160a01b031630613775565b60d1546001600160a01b0316613942565b6116b2610fe8565b50505b5050505050565b6033546001600160a01b031633146117165760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610949565b610e3e600061399b565b6033546001600160a01b03163314806117cf575060d260009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561178257600080fd5b505afa158015611796573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117ba9190614c7d565b6001600160a01b0316336001600160a01b0316145b6040518060400160405280600381526020016231313160e81b815250906118095760405162461bcd60e51b81526004016109499190615302565b5060408051808201909152600381526203133360ec1b60208201526001600160a01b03821661184b5760405162461bcd60e51b81526004016109499190615302565b5060d180546001600160a01b0319166001600160a01b0383169081179091556040519081527f623e52a82ff2bab02a51be01f76b0b3178bbafcbe15c455b7ca4c9615b8da598906020015b60405180910390a150565b6033546001600160a01b0316331480611950575060d260009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561190357600080fd5b505afa158015611917573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193b9190614c7d565b6001600160a01b0316336001600160a01b0316145b6040518060400160405280600381526020016231313160e81b8152509061198a5760405162461bcd60e51b81526004016109499190615302565b5060408051808201909152600381526203133360ec1b60208201526001600160a01b0382166119cc5760405162461bcd60e51b81526004016109499190615302565b5060d480546001600160a01b0319166001600160a01b0383169081179091556040519081527f0e05ae75e8b926552cf6fcd744d19f422561e3ced1e426868730852702dbe41890602001611896565b60d354609854604051627eeac760e11b81526001600160a01b038481166004830152600160a01b9092046001600160401b03166024820152600092919091169062fdd58e90604401610e70565b6002609a541415611abb5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610949565b6002609a55611ac8610fe8565b610a51816139ed565b611ad9610fe8565b611ae282613363565b611aeb816139ed565b5050565b6033546001600160a01b03163314611b495760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610949565b610e3e613d01565b60d45460975460985460d65460405163721adea760e01b81526001600160a01b039384166004820152918316602483015260ff1660448201526000928392169063721adea79060640160206040518083038186803b158015611bb257600080fd5b505afa158015611bc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bea919061502f565b60d654909150600090611c0690610100900460ff16600a61544b565b611c1083876154f3565b611c1a91906153e8565b90508315611c775760cc5460cd546001600160401b03600160401b80840482169390830482169290821691611c509116856154f3565b611c5a91906154f3565b611c6491906153e8565b611c6e91906153e8565b92505050610ec0565b9150610ec09050565b6033546001600160a01b03163314611cda5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610949565b60408051808201909152600381526203133360ec1b60208201526001600160a01b038216611d1b5760405162461bcd60e51b81526004016109499190615302565b5060d280546001600160a01b0319166001600160a01b0383169081179091556040519081527fa05e64ea7e34b372177317c71229808e25bdbfe5dc3e6bc4fc7ca66c97d9327690602001611896565b609754604051631da0b5cf60e31b81526001600160a01b03918216600482015260009183169063ed05ae7890602401610e70565b6033546001600160a01b0316331480611e4d575060d260009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b158015611e0057600080fd5b505afa158015611e14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e389190614c7d565b6001600160a01b0316336001600160a01b0316145b6040518060400160405280600381526020016231313160e81b81525090611e875760405162461bcd60e51b81526004016109499190615302565b5060408051808201909152600381526203133360ec1b60208201526001600160a01b038216611ec95760405162461bcd60e51b81526004016109499190615302565b5060d380546001600160a01b0319166001600160a01b0383169081179091556040516330e2d1ed60e01b81526330e2d1ed90611f0c9060009030906004016152a4565b602060405180830381600087803b158015611f2657600080fd5b505af1158015611f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5e91906150f4565b609880546001600160401b0392909216600160a01b027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff9092169190911790556040516330e2d1ed60e01b81526001600160a01b038216906330e2d1ed90611fcd9060019030906004016152a4565b602060405180830381600087803b158015611fe757600080fd5b505af1158015611ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201f91906150f4565b6099805467ffffffffffffffff19166001600160401b03929092169190911790556040516001600160a01b03821681527fb89c4162816fee2afc84abac7e339928e379cd5d1d61acadaa52a39ce2650b6b90602001611896565b6033546001600160a01b0316331480612128575060d260009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156120db57600080fd5b505afa1580156120ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121139190614c7d565b6001600160a01b0316336001600160a01b0316145b6040518060400160405280600381526020016231313160e81b815250906121625760405162461bcd60e51b81526004016109499190615302565b50600081600381111561218557634e487b7160e01b600052602160045260246000fd5b141561220857816001600160401b0316836001600160401b0316116040518060400160405280600381526020016233303160e81b815250906121da5760405162461bcd60e51b81526004016109499190615302565b5060cc80546001600160401b03848116600160401b026001600160801b031990921690861617179055612428565b600181600381111561222a57634e487b7160e01b600052602160045260246000fd5b14156122ad57816001600160401b0316836001600160401b0316116040518060400160405280600381526020016233303160e81b8152509061227f5760405162461bcd60e51b81526004016109499190615302565b5060cd80546001600160401b03848116600160401b026001600160801b031990921690861617179055612428565b60028160038111156122cf57634e487b7160e01b600052602160045260246000fd5b141561235257816001600160401b0316836001600160401b0316106040518060400160405280600381526020016233303160e81b815250906123245760405162461bcd60e51b81526004016109499190615302565b5060ce80546001600160401b03848116600160401b026001600160801b031990921690861617179055612428565b600381600381111561237457634e487b7160e01b600052602160045260246000fd5b14156123f757816001600160401b0316836001600160401b0316106040518060400160405280600381526020016233303160e81b815250906123c95760405162461bcd60e51b81526004016109499190615302565b5060cf80546001600160401b03848116600160401b026001600160801b031990921690861617179055612428565b60408051808201825260038152620c4ccd60ea1b6020820152905162461bcd60e51b81526109499190600401615302565b7f684344b55402a828ac72dba82a6cdde8094ee32955d4c34d290d43d1a703612281848460405161245b939291906152d0565b60405180910390a1505050565b612470610fe8565b610c0a81613d7c565b612481610fe8565b61248a82613d7c565b611aeb81613f1d565b6002609a5414156124e65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610949565b6002609a556124f3610fe8565b610a5181613f1d565b60d260009054906101000a90046001600160a01b03166001600160a01b0316637fabc90b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561254a57600080fd5b505afa15801561255e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125829190614c7d565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b815250906125d05760405162461bcd60e51b81526004016109499190615302565b5060655460ff16156126175760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610949565b6000805b60d05481101561267c5760d0818154811061264657634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b038681169116141561266a57600191505b8061267481615590565b91505061261b565b50806126b357604080518082018252600381526231333560e81b6020820152905162461bcd60e51b81526109499190600401615302565b60d154609854604051637d6af07960e01b81526001600160a01b0391821660048201526000929190911690637d6af0799060240160206040518083038186803b1580156126ff57600080fd5b505afa158015612713573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612737919061502f565b61274985670de0b6b3a76400006154f3565b61275391906153e8565b60d15490915061276d9085906001600160a01b03166142b2565b60d154609754604051631da0b5cf60e31b81526001600160a01b039182166004820152600092670de0b6b3a764000092859291169063ed05ae789060240160206040518083038186803b1580156127c357600080fd5b505afa1580156127d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127fb919061502f565b61280591906154f3565b61280f91906153e8565b60d1549091506128299082906001600160a01b031661323a565b6128338187613942565b61284661284085876153d0565b8761430b565b6128673361285486886153d0565b6098546001600160a01b03169190613293565b60d154604080516001600160a01b03928316815291881660208301528101869052606081018290527f06792f8797628d4ae9a2a9ec4ff047ef0d1f3fca2c413ec76165fd8c5b125bd99060800160405180910390a1505050505050565b60d354609954604051627eeac760e11b81526001600160a01b0384811660048301526001600160401b0390921660248201526000928392169062fdd58e9060440160206040518083038186803b15801561291d57600080fd5b505afa158015612931573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612955919061502f565b90506129618382614364565b9392505050565b60d260009054906101000a90046001600160a01b03166001600160a01b031663b8491a846040518163ffffffff1660e01b815260040160206040518083038186803b1580156129b657600080fd5b505afa1580156129ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ee9190614c7d565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b81525090612a3c5760405162461bcd60e51b81526004016109499190615302565b506000805b8351811015612c075760006001600160a01b0316848281518110612a7557634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031614612bf5574260d76000868481518110612ab057634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002081905550600060d360009054906101000a90046001600160a01b03166001600160a01b031662fdd58e868481518110612b2157634e487b7160e01b600052603260045260246000fd5b602090810291909101015160995460405160e084901b6001600160e01b03191681526001600160a01b0390921660048301526001600160401b0316602482015260440160206040518083038186803b158015612b7c57600080fd5b505afa158015612b90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bb4919061502f565b9050612be7858381518110612bd957634e487b7160e01b600052603260045260246000fd5b602002602001015182614364565b612bf190846153d0565b9250505b80612bff81615590565b915050612a41565b50612c26612c158284615512565b60d1546001600160a01b03166142b2565b8060d86000828254612c3891906153d0565b9091555050505050565b60cf546000906001600160401b03600160401b8204811691612c659116846154f3565b610ec091906153e8565b606060d0805480602002602001604051908101604052809291908181526020018280548015612cc757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612ca9575b5050505050905090565b6033546001600160a01b03163314612d2b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610949565b6001600160a01b038116612d905760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610949565b610c0a8161399b565b6000612da560016143ce565b90508015612dbd576000805461ff0019166101001790555b6001600160a01b03851615801590612ddd57506001600160a01b03841615155b8015612df157506001600160a01b03831615155b8015612e0557506001600160a01b03821615155b6040518060400160405280600381526020016203133360ec1b81525090612e3f5760405162461bcd60e51b81526004016109499190615302565b50612e486144e4565b612e50614513565b612e58614542565b60d280546001600160a01b038088166001600160a01b03199283161790925560d480548784169083161790556097805486841690831681179091556098805493861693909216929092179055606090819073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415612ef5576040805180820190915260068152654e415449564560d01b602082015260d6805460ff191660121790559150612ff2565b846001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b158015612f2e57600080fd5b505afa158015612f42573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612f6a9190810190614f4c565b9150846001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612fa557600080fd5b505afa158015612fb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fdd919061515d565b60d6805460ff191660ff929092169190911790555b6001600160a01b03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561304957506040805180820190915260068152654e415449564560d01b602082015260d6805461ff00191661120017905561314c565b836001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801561308257600080fd5b505afa158015613096573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526130be9190810190614f4c565b9050836001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156130f957600080fd5b505afa15801561310d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613131919061515d565b60d660016101000a81548160ff021916908360ff1602179055505b818160405160200161315f9291906151c6565b60405160208183030381529060405260d59080519060200190613183929190614b84565b505060cc80546001600160801b0319908116681400000000000000151790915560cd80548216683f000000000000005017905560cf805482166814000000000000000117905560ce80549091166903e800000000000000011790555080156116b5576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6001600160a01b03163b151590565b6097546040516001600160a01b0390911660248201526044810183905260009060640160408051601f198184030181529190526020810180516001600160e01b031663f3fef3a360e01b17905290506111dc8282614571565b801561335e576132a2836146ab565b1561334a576000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146132f4576040519150601f19603f3d011682016040523d82523d6000602084013e6132f9565b606091505b50509050806111dc5760405162461bcd60e51b815260206004820152601560248201527f4661696c656420746f2073656e64204e617469766500000000000000000000006044820152606401610949565b61335e6001600160a01b03841683836146e4565b505050565b60d354609954604051627eeac760e11b81523360048201526001600160401b0390911660248201526000916001600160a01b03169062fdd58e9060440160206040518083038186803b1580156133b857600080fd5b505afa1580156133cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133f0919061502f565b905060006133fe3383614364565b9050808311801561340f5750600082115b6040518060400160405280600381526020016218981b60e91b815250906134495760405162461bcd60e51b81526004016109499190615302565b5060008084126134595783613463565b61346382846153d0565b6098549091506001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156134e757803410156040518060400160405280600381526020016231303360e81b815250906134cb5760405162461bcd60e51b81526004016109499190615302565b50803411156134e2576134e2336128548334615512565b6135bd565b609854604051636eb1769f60e11b815233600482015230602482015282916001600160a01b03169063dd62ed3e9060440160206040518083038186803b15801561353057600080fd5b505afa158015613544573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613568919061502f565b10156040518060400160405280600381526020016231303760e81b815250906135a45760405162461bcd60e51b81526004016109499190615302565b506098546135bd906001600160a01b0316333084614747565b6135ca612c158383615512565b60d3546099546001600160a01b039091169063f5298aca9033906001600160401b03166135f78686615512565b6040516001600160e01b031960e086901b1681526001600160a01b0390931660048401526001600160401b0390911660248301526044820152606401600060405180830381600087803b15801561364d57600080fd5b505af1158015613661573d6000803e3d6000fd5b505033600090815260d76020526040812042905560d8805486945090925061368a9084906153d0565b90915550506098546040518281526001600160a01b039091169033907ffc2d2b4b3ad857c1c0893799f86b421efff822709b26de93df5709671f4841ca9060200160405180910390a350505050565b60655460ff1661372b5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610949565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6000613780836146ab565b1561379657506001600160a01b03811631610ec0565b6040516370a0823160e01b81526001600160a01b0383811660048301528416906370a082319060240160206040518083038186803b1580156137d757600080fd5b505afa1580156137eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061380f919061502f565b9050610ec0565b61381f836146ab565b1561386c5760405162461bcd60e51b815260206004820152601860248201527f417070726f76652063616c6c6564206f6e204e617469766500000000000000006044820152606401610949565b806138865761335e6001600160a01b03841683600061477f565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e9060440160206040518083038186803b1580156138d157600080fd5b505afa1580156138e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613909919061502f565b9050818110156111dc57801561392e5761392e6001600160a01b03851684600061477f565b6111dc6001600160a01b038516848461477f565b6097546040516001600160a01b0390911660248201526044810183905260009060640160408051601f198184030181529190526020810180516001600160e01b03166311f9fbc960e21b17905290506111dc8282614571565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60d354609854604051627eeac760e11b8152336004820152600160a01b9091046001600160401b031660248201526000916001600160a01b03169062fdd58e9060440160206040518083038186803b158015613a4857600080fd5b505afa158015613a5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a80919061502f565b9050600081116040518060400160405280600381526020016218989960e91b81525090613ac05760405162461bcd60e51b81526004016109499190615302565b5060d354609954604051627eeac760e11b81523360048201526001600160401b039091166024820152600091613b5b916001600160a01b039091169062fdd58e9060440160206040518083038186803b158015613b1c57600080fd5b505afa158015613b30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b54919061502f565b6001611b51565b90506000808412613b6c5783613b76565b613b768284615512565b90508015801590613b90575081613b8d8285615512565b10155b604051806040016040528060038152602001620c4c0d60ea1b81525090613bca5760405162461bcd60e51b81526004016109499190615302565b50609754600090613be4906001600160a01b031630613775565b60d154909150613bfe9083906001600160a01b031661323a565b6097548190613c16906001600160a01b031630613775565b613c209190615512565b60d354609854604051637a94c56560e11b8152336004820152600160a01b9091046001600160401b03166024820152604481018390529193506001600160a01b03169063f5298aca90606401600060405180830381600087803b158015613c8657600080fd5b505af1158015613c9a573d6000803e3d6000fd5b5050609754613cb692506001600160a01b031690503384613293565b6097546040518381526001600160a01b039091169033907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb9060200160405180910390a35050505050565b60655460ff1615613d475760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610949565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586137583390565b6097546001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613df1578034148015613db157508015155b6040518060400160405280600381526020016231303360e81b81525090613deb5760405162461bcd60e51b81526004016109499190615302565b50613e42565b60408051808201909152600381526231303360e81b602082015281613e295760405162461bcd60e51b81526004016109499190615302565b50609754613e42906001600160a01b0316333084614747565b60d154613e599082906001600160a01b0316613942565b60d354609854604051630ab714fb60e11b8152336004820152600160a01b9091046001600160401b03166024820152604481018390526001600160a01b039091169063156e29f690606401600060405180830381600087803b158015613ebe57600080fd5b505af1158015613ed2573d6000803e3d6000fd5b50506097546040518481526001600160a01b0390911692503391507f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f629060200160405180910390a350565b60d354609854604051627eeac760e11b8152336004820152600160a01b9091046001600160401b031660248201526000916001600160a01b03169062fdd58e9060440160206040518083038186803b158015613f7857600080fd5b505afa158015613f8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fb0919061502f565b60d354609954604051627eeac760e11b81523360048201526001600160401b0390911660248201529192506000916001600160a01b039091169062fdd58e9060440160206040518083038186803b15801561400a57600080fd5b505afa15801561401e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614042919061502f565b9050600061405082856153d0565b9050600061405f826001611b51565b9050841580159061406f57508084115b6040518060400160405280600381526020016231303560e81b815250906140a95760405162461bcd60e51b81526004016109499190615302565b506098546000906140c3906001600160a01b031630613775565b60d1549091506140dd9087906001600160a01b031661430b565b60985481906140f5906001600160a01b031630613775565b6140ff9190615512565b955061410b84876153d0565b60ce5433600090815260d76020526040812054929550916301e13380916001600160401b03600160401b82048116929116906141479042615512565b61415190896154f3565b61415b91906154f3565b61416591906153e8565b61416f91906153e8565b60ce5490915084906001600160401b03600160401b8204811691166141986301e13380856154f3565b6141a291906154f3565b6141ac91906153e8565b6141b691906153e8565b6141c09042615512565b33600081815260d76020526040908190209290925560d3546099549251630ab714fb60e11b815260048101929092526001600160401b039092166024820152604481018990526001600160a01b039091169063156e29f690606401600060405180830381600087803b15801561423557600080fd5b505af1158015614249573d6000803e3d6000fd5b505060985461426592506001600160a01b031690503389613293565b6098546040518881526001600160a01b039091169033907f312a5e5e1079f5dda4e95dbbd0b908b291fd5b992ef22073643ab691572c5b529060200160405180910390a350505050505050565b6098546040516001600160a01b0390911660248201526044810183905260009060640160408051601f198184030181529190526020810180516001600160e01b03166306bdb15760e31b17905290506111dc8282614571565b6098546040516001600160a01b0390911660248201526044810183905260009060640160408051601f198184030181529190526020810180516001600160e01b0316634b8a352960e01b17905290506111dc8282614571565b60ce546001600160a01b038316600090815260d7602052604081205490916301e13380916001600160401b03600160401b830481169216906143a69042615512565b6143b090866154f3565b6143ba91906154f3565b6143c491906153e8565b61296191906153e8565b60008054610100900460ff161561445c578160ff1660011480156143f15750303b155b6144545760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610949565b506000919050565b60005460ff8084169116106144ca5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610949565b506000805460ff191660ff92909216919091179055600190565b600054610100900460ff1661450b5760405162461bcd60e51b815260040161094990615315565b610e3e6148aa565b600054610100900460ff1661453a5760405162461bcd60e51b815260040161094990615315565b610e3e6148da565b600054610100900460ff166145695760405162461bcd60e51b815260040161094990615315565b610e3e61490d565b606061457f60655460ff1690565b156145bf5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610949565b60408051808201909152600381526231313760e81b60208201526001600160a01b0384163b6146015760405162461bcd60e51b81526004016109499190615302565b50600080846001600160a01b03168460405161461d91906151aa565b600060405180830381855af49150503d8060008114614658576040519150601f19603f3d011682016040523d82523d6000602084013e61465d565b606091505b50915091506146a282826040518060400160405280602081526020017f64656c65676174652063616c6c20746f2070726f7669646572206661696c656481525061493b565b95945050505050565b60006001600160a01b0382161580610ec057506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b6040516001600160a01b03831660248201526044810182905261335e90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614974565b6040516001600160a01b03808516602483015283166044820152606481018290526111dc9085906323b872dd60e01b90608401614710565b8015806148085750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156147ce57600080fd5b505afa1580156147e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614806919061502f565b155b61487a5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610949565b6040516001600160a01b03831660248201526044810182905261335e90849063095ea7b360e01b90606401614710565b600054610100900460ff166148d15760405162461bcd60e51b815260040161094990615315565b610e3e3361399b565b600054610100900460ff166149015760405162461bcd60e51b815260040161094990615315565b6065805460ff19169055565b600054610100900460ff166149345760405162461bcd60e51b815260040161094990615315565b6001609a55565b6060831561494a575081612961565b82511561495a5782518084602001fd5b8160405162461bcd60e51b81526004016109499190615302565b60006149c9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614a469092919063ffffffff16565b80519091501561335e57808060200190518101906149e79190614ef7565b61335e5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610949565b6060610bf18484600085856001600160a01b0385163b614aa85760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610949565b600080866001600160a01b03168587604051614ac491906151aa565b60006040518083038185875af1925050503d8060008114614b01576040519150601f19603f3d011682016040523d82523d6000602084013e614b06565b606091505b5091509150614b1682828661493b565b979650505050505050565b828054828255906000526020600020908101928215614b74579160200282015b82811115614b745781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190614b41565b50614b80929150614bf8565b5090565b828054614b9090615555565b90600052602060002090601f016020900481019282614bb25760008555614b74565b82601f10614bcb57805160ff1916838001178555614b74565b82800160010185558215614b74579182015b82811115614b74578251825591602001919060010190614bdd565b5b80821115614b805760008155600101614bf9565b6000614c20614c1b846153a9565b615379565b9050828152838383011115614c3457600080fd5b612961836020830184615529565b600082601f830112614c52578081fd5b61296183835160208501614c0d565b600060208284031215614c72578081fd5b8135612961816155ed565b600060208284031215614c8e578081fd5b8151612961816155ed565b60008060008060808587031215614cae578283fd5b8435614cb9816155ed565b93506020850135614cc9816155ed565b92506040850135614cd9816155ed565b91506060850135614ce9816155ed565b939692955090935050565b60008060408385031215614d06578081fd5b8251614d11816155ed565b60208401519092506001600160401b0380821115614d2d578283fd5b9084019060408287031215614d40578283fd5b604051604081018181108382111715614d5b57614d5b6155d7565b6040528251614d69816155ed565b8152602083015182811115614d7c578485fd5b614d8888828601614c42565b6020830152508093505050509250929050565b600080600060608486031215614daf578081fd5b8335614dba816155ed565b95602085013595506040909401359392505050565b60008060208385031215614de1578182fd5b82356001600160401b0380821115614df7578384fd5b818501915085601f830112614e0a578384fd5b813581811115614e18578485fd5b8660208260051b8501011115614e2c578485fd5b60209290920196919550909350505050565b60008060408385031215614e50578182fd5b82356001600160401b0380821115614e66578384fd5b818501915085601f830112614e79578384fd5b8135602082821115614e8d57614e8d6155d7565b8160051b9250614e9e818401615379565b8281528181019085830185870184018b1015614eb8578889fd5b8896505b84871015614ee65780359550614ed1866155ed565b85835260019690960195918301918301614ebc565b509997909101359750505050505050565b600060208284031215614f08578081fd5b815161296181615602565b600060208284031215614f24578081fd5b5035919050565b60008060408385031215614f3d578182fd5b50508035926020909101359150565b600060208284031215614f5d578081fd5b81516001600160401b03811115614f72578182fd5b8201601f81018413614f82578182fd5b610bf184825160208401614c0d565b600060208284031215614fa2578081fd5b81516001600160401b0380821115614fb8578283fd5b9083019060608286031215614fcb578283fd5b604051606081018181108382111715614fe657614fe66155d7565b6040528251614ff4816155ed565b8152602083015182811115615007578485fd5b61501387828601614c42565b6020830152506040830151604082015280935050505092915050565b600060208284031215615040578081fd5b5051919050565b60008060408385031215615059578182fd5b82359150602083013561506b81615602565b809150509250929050565b60008060408385031215615088578182fd5b8235915060208301356001600160401b038111156150a4578182fd5b8301601f810185136150b4578182fd5b80356150c2614c1b826153a9565b8181528660208385010111156150d6578384fd5b81602084016020830137908101602001929092525090939092509050565b600060208284031215615105578081fd5b815161296181615610565b600080600060608486031215615124578081fd5b833561512f81615610565b9250602084013561513f81615610565b9150604084013560048110615152578182fd5b809150509250925092565b60006020828403121561516e578081fd5b815160ff81168114612961578182fd5b60008151808452615196816020860160208601615529565b601f01601f19169290920160200192915050565b600082516151bc818460208701615529565b9190910192915050565b6415985d5b1d60da1b8152600083516151e6816005850160208801615529565b8351908301906151fd816005840160208801615529565b01600501949350505050565b60208082528181018390526000908460408401835b8681101561524c578235615231816155ed565b6001600160a01b03168252918301919083019060010161521e565b509695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156152985783516001600160a01b031683529284019291840191600101615273565b50909695505050505050565b60408101600284106152b8576152b86155c1565b9281526001600160a01b039190911660209091015290565b60608101600485106152e4576152e46155c1565b9381526001600160401b039283166020820152911660409091015290565b602081526000612961602083018461517e565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b828152604060208201526000610bf1604083018461517e565b604051601f8201601f191681016001600160401b03811182821017156153a1576153a16155d7565b604052919050565b60006001600160401b038211156153c2576153c26155d7565b50601f01601f191660200190565b600082198211156153e3576153e36155ab565b500190565b60008261540357634e487b7160e01b81526012600452602481fd5b500490565b600181815b80851115615443578160001904821115615429576154296155ab565b8085161561543657918102915b93841c939080029061540d565b509250929050565b6000612961838360008261546157506001610ec0565b8161546e57506000610ec0565b8160018114615484576002811461548e576154aa565b6001915050610ec0565b60ff84111561549f5761549f6155ab565b50506001821b610ec0565b5060208310610133831016604e8410600b84101617156154cd575081810a610ec0565b6154d78383615408565b80600019048211156154eb576154eb6155ab565b029392505050565b600081600019048311821515161561550d5761550d6155ab565b500290565b600082821015615524576155246155ab565b500390565b60005b8381101561554457818101518382015260200161552c565b838111156111dc5750506000910152565b600181811c9082168061556957607f821691505b6020821081141561558a57634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156155a4576155a46155ab565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610c0a57600080fd5b8015158114610c0a57600080fd5b6001600160401b0381168114610c0a57600080fdfea2646970667358221220c953783e362a54ecad874fb7007b23fa77c79f535731e3c45a9717a189aadc8964736f6c63430008040033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 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.