More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 55 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Flash Close | 20023877 | 66 days ago | IN | 0 ETH | 0.00759061 | ||||
Flash Close | 20002011 | 69 days ago | IN | 0 ETH | 0.00481099 | ||||
Flash Close | 19307792 | 166 days ago | IN | 0 ETH | 0.02823067 | ||||
Flash Close | 17805313 | 376 days ago | IN | 0 ETH | 0.01531195 | ||||
Flash Close | 17805284 | 376 days ago | IN | 0 ETH | 0.01456312 | ||||
Flash Close | 17684192 | 393 days ago | IN | 0 ETH | 0.01685884 | ||||
Flash Close | 17457558 | 425 days ago | IN | 0 ETH | 0.01700119 | ||||
Flash Close | 17290959 | 449 days ago | IN | 0 ETH | 0.03616379 | ||||
Flash Close | 15331568 | 728 days ago | IN | 0 ETH | 0.01206259 | ||||
Flash Close | 15109628 | 762 days ago | IN | 0 ETH | 0.00945791 | ||||
Flash Close | 15027623 | 776 days ago | IN | 0 ETH | 0.01498878 | ||||
Flash Batch Liqu... | 14966686 | 787 days ago | IN | 0 ETH | 0.12993763 | ||||
Flash Batch Liqu... | 14966589 | 787 days ago | IN | 0 ETH | 0.02457067 | ||||
Flash Batch Liqu... | 14966507 | 787 days ago | IN | 0 ETH | 0.11829425 | ||||
Flash Batch Liqu... | 14966455 | 787 days ago | IN | 0 ETH | 0.03260166 | ||||
Flash Batch Liqu... | 14950727 | 789 days ago | IN | 0 ETH | 0.0094427 | ||||
Flash Batch Liqu... | 14948823 | 790 days ago | IN | 0 ETH | 0.05209989 | ||||
Flash Batch Liqu... | 14948749 | 790 days ago | IN | 0 ETH | 0.0143304 | ||||
Flash Batch Liqu... | 14865237 | 804 days ago | IN | 0 ETH | 0.00325837 | ||||
Flash Batch Liqu... | 14865235 | 804 days ago | IN | 0 ETH | 0.00379871 | ||||
Flash Close | 14864909 | 804 days ago | IN | 0 ETH | 0.01105458 | ||||
Flash Close | 14803211 | 814 days ago | IN | 0 ETH | 0.0130988 | ||||
Flash Batch Liqu... | 14760378 | 820 days ago | IN | 0 ETH | 0.15535345 | ||||
Flash Batch Liqu... | 14760347 | 820 days ago | IN | 0 ETH | 0.59338367 | ||||
Flash Close | 14750775 | 822 days ago | IN | 0 ETH | 0.05241601 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
20023877 | 66 days ago | 0.00003413 ETH | ||||
20023877 | 66 days ago | 0.00003413 ETH | ||||
20023877 | 66 days ago | 0.00301966 ETH | ||||
20023877 | 66 days ago | 0.04844186 ETH | ||||
20023877 | 66 days ago | 0.05146153 ETH | ||||
20002011 | 69 days ago | 0.00000018 ETH | ||||
20002011 | 69 days ago | 0.00000018 ETH | ||||
20002011 | 69 days ago | 0.00001638 ETH | ||||
20002011 | 69 days ago | 0.03260958 ETH | ||||
20002011 | 69 days ago | 0.03262596 ETH | ||||
19307792 | 166 days ago | 0.00465901 ETH | ||||
19307792 | 166 days ago | 0.00465901 ETH | ||||
19307792 | 166 days ago | 0.35613539 ETH | ||||
19307792 | 166 days ago | 0.15840136 ETH | ||||
19307792 | 166 days ago | 0.51453676 ETH | ||||
17805313 | 376 days ago | 0.00060115 ETH | ||||
17805313 | 376 days ago | 0.00060115 ETH | ||||
17805313 | 376 days ago | 0.05652708 ETH | ||||
17805313 | 376 days ago | 0.04450144 ETH | ||||
17805313 | 376 days ago | 0.10102852 ETH | ||||
17805284 | 376 days ago | 0.00064697 ETH | ||||
17805284 | 376 days ago | 0.00064697 ETH | ||||
17805284 | 376 days ago | 0.05652707 ETH | ||||
17805284 | 376 days ago | 0.04450145 ETH | ||||
17805284 | 376 days ago | 0.10102852 ETH |
Loading...
Loading
Contract Name:
Fliquidator
Compiler Version
v0.6.12+commit.27d51765
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity >=0.6.12; pragma experimental ABIEncoderV2; import { IVault } from "./Vaults/IVault.sol"; import { IFujiAdmin } from "./IFujiAdmin.sol"; import { IFujiERC1155 } from "./FujiERC1155/IFujiERC1155.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { Flasher } from "./Flashloans/Flasher.sol"; import { FlashLoan } from "./Flashloans/LibFlashLoan.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { Errors } from "./Libraries/Errors.sol"; import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; import { LibUniversalERC20 } from "./Libraries/LibUniversalERC20.sol"; import { IUniswapV2Router02 } from "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; interface IVaultExt is IVault { //Asset Struct struct VaultAssets { address collateralAsset; address borrowAsset; uint64 collateralID; uint64 borrowID; } function vAssets() external view returns (VaultAssets memory); } interface IFujiERC1155Ext is IFujiERC1155 { function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); } contract Fliquidator is Ownable, ReentrancyGuard { using SafeMath for uint256; using LibUniversalERC20 for IERC20; struct Factor { uint64 a; uint64 b; } // Flash Close Fee Factor Factor public flashCloseF; IFujiAdmin private _fujiAdmin; IUniswapV2Router02 public swapper; // Log Liquidation event Liquidate( address indexed userAddr, address liquidator, address indexed asset, uint256 amount ); // Log FlashClose event FlashClose(address indexed userAddr, address indexed asset, uint256 amount); // Log Liquidation event FlashLiquidate(address userAddr, address liquidator, address indexed asset, uint256 amount); modifier isAuthorized() { require(msg.sender == owner(), Errors.VL_NOT_AUTHORIZED); _; } modifier onlyFlash() { require(msg.sender == _fujiAdmin.getFlasher(), Errors.VL_NOT_AUTHORIZED); _; } modifier isValidVault(address _vaultAddr) { require(_fujiAdmin.validVault(_vaultAddr), "Invalid vault!"); _; } constructor() public { // 1.013 flashCloseF.a = 1013; flashCloseF.b = 1000; } receive() external payable {} // FLiquidator Core Functions /** * @dev Liquidate an undercollaterized debt and get bonus (bonusL in Vault) * @param _userAddrs: Address array of users whose position is liquidatable * @param _vault: Address of the vault in where liquidation will occur */ function batchLiquidate(address[] calldata _userAddrs, address _vault) external nonReentrant isValidVault(_vault) { // Update Balances at FujiERC1155 IVault(_vault).updateF1155Balances(); // Create Instance of FujiERC1155 IFujiERC1155Ext f1155 = IFujiERC1155Ext(IVault(_vault).fujiERC1155()); // Struct Instance to get Vault Asset IDs in f1155 IVaultExt.VaultAssets memory vAssets = IVaultExt(_vault).vAssets(); address[] memory formattedUserAddrs = new address[](2 * _userAddrs.length); uint256[] memory formattedIds = new uint256[](2 * _userAddrs.length); // Build the required Arrays to query balanceOfBatch from f1155 for (uint256 i = 0; i < _userAddrs.length; i++) { formattedUserAddrs[2 * i] = _userAddrs[i]; formattedUserAddrs[2 * i + 1] = _userAddrs[i]; formattedIds[2 * i] = vAssets.collateralID; formattedIds[2 * i + 1] = vAssets.borrowID; } // Get user Collateral and Debt Balances uint256[] memory usrsBals = f1155.balanceOfBatch(formattedUserAddrs, formattedIds); uint256 neededCollateral; uint256 debtBalanceTotal; for (uint256 i = 0; i < formattedUserAddrs.length; i += 2) { // Compute Amount of Minimum Collateral Required including factors neededCollateral = IVault(_vault).getNeededCollateralFor(usrsBals[i + 1], true); // Check if User is liquidatable if (usrsBals[i] < neededCollateral) { // If true, add User debt balance to the total balance to be liquidated debtBalanceTotal = debtBalanceTotal.add(usrsBals[i + 1]); } else { // Replace User that is not liquidatable by Zero Address formattedUserAddrs[i] = address(0); formattedUserAddrs[i + 1] = address(0); } } // Check there is at least one user liquidatable require(debtBalanceTotal > 0, Errors.VL_USER_NOT_LIQUIDATABLE); // Check Liquidator Allowance require( IERC20(vAssets.borrowAsset).allowance(msg.sender, address(this)) >= debtBalanceTotal, Errors.VL_MISSING_ERC20_ALLOWANCE ); // Transfer borrowAsset funds from the Liquidator to Here IERC20(vAssets.borrowAsset).transferFrom(msg.sender, address(this), debtBalanceTotal); // Transfer Amount to Vault IERC20(vAssets.borrowAsset).univTransfer(payable(_vault), debtBalanceTotal); // TODO: Get => corresponding amount of BaseProtocol Debt and FujiDebt // Repay BaseProtocol debt IVault(_vault).payback(int256(debtBalanceTotal)); //TODO: Transfer corresponding Debt Amount to Fuji Treasury // Compute the Liquidator Bonus bonusL uint256 globalBonus = IVault(_vault).getLiquidationBonusFor(debtBalanceTotal, false); // Compute how much collateral needs to be swapt uint256 globalCollateralInPlay = _getCollateralInPlay(vAssets.borrowAsset, debtBalanceTotal.add(globalBonus)); // Burn Collateral f1155 tokens for each liquidated user _burnMultiLoop(formattedUserAddrs, usrsBals, IVault(_vault), f1155, vAssets); // Withdraw collateral IVault(_vault).withdraw(int256(globalCollateralInPlay)); // Swap Collateral _swap(vAssets.borrowAsset, debtBalanceTotal.add(globalBonus), globalCollateralInPlay); // Transfer to Liquidator the debtBalance + bonus IERC20(vAssets.borrowAsset).univTransfer(msg.sender, debtBalanceTotal.add(globalBonus)); // Burn Debt f1155 tokens and Emit Liquidation Event for Each Liquidated User for (uint256 i = 0; i < formattedUserAddrs.length; i += 2) { if (formattedUserAddrs[i] != address(0)) { f1155.burn(formattedUserAddrs[i], vAssets.borrowID, usrsBals[i + 1]); emit Liquidate(formattedUserAddrs[i], msg.sender, vAssets.borrowAsset, usrsBals[i + 1]); } } } /** * @dev Initiates a flashloan used to repay partially or fully the debt position of msg.sender * @param _amount: Pass -1 to fully close debt position, otherwise Amount to be repaid with a flashloan * @param _vault: The vault address where the debt position exist. * @param _flashnum: integer identifier of flashloan provider */ function flashClose( int256 _amount, address _vault, uint8 _flashnum ) external nonReentrant isValidVault(_vault) { Flasher flasher = Flasher(payable(_fujiAdmin.getFlasher())); // Update Balances at FujiERC1155 IVault(_vault).updateF1155Balances(); // Create Instance of FujiERC1155 IFujiERC1155Ext f1155 = IFujiERC1155Ext(IVault(_vault).fujiERC1155()); // Struct Instance to get Vault Asset IDs in f1155 IVaultExt.VaultAssets memory vAssets = IVaultExt(_vault).vAssets(); // Get user Balances uint256 userCollateral = f1155.balanceOf(msg.sender, vAssets.collateralID); uint256 userDebtBalance = f1155.balanceOf(msg.sender, vAssets.borrowID); // Check Debt is > zero require(userDebtBalance > 0, Errors.VL_NO_DEBT_TO_PAYBACK); uint256 amount = _amount < 0 ? userDebtBalance : uint256(_amount); uint256 neededCollateral = IVault(_vault).getNeededCollateralFor(amount, false); require(userCollateral >= neededCollateral, Errors.VL_UNDERCOLLATERIZED_ERROR); address[] memory userAddressArray = new address[](1); userAddressArray[0] = msg.sender; FlashLoan.Info memory info = FlashLoan.Info({ callType: FlashLoan.CallType.Close, asset: vAssets.borrowAsset, amount: amount, vault: _vault, newProvider: address(0), userAddrs: userAddressArray, userBalances: new uint256[](0), userliquidator: address(0), fliquidator: address(this) }); flasher.initiateFlashloan(info, _flashnum); } /** * @dev Close user's debt position by using a flashloan * @param _userAddr: user addr to be liquidated * @param _vault: Vault address * @param _amount: amount received by Flashloan * @param _flashloanFee: amount extra charged by flashloan provider * Emits a {FlashClose} event. */ function executeFlashClose( address payable _userAddr, address _vault, uint256 _amount, uint256 _flashloanFee ) external onlyFlash { // Create Instance of FujiERC1155 IFujiERC1155 f1155 = IFujiERC1155(IVault(_vault).fujiERC1155()); // Struct Instance to get Vault Asset IDs in f1155 IVaultExt.VaultAssets memory vAssets = IVaultExt(_vault).vAssets(); // Get user Collateral and Debt Balances uint256 userCollateral = f1155.balanceOf(_userAddr, vAssets.collateralID); uint256 userDebtBalance = f1155.balanceOf(_userAddr, vAssets.borrowID); // Get user Collateral + Flash Close Fee to close posisition, for _amount passed uint256 userCollateralInPlay = IVault(_vault) .getNeededCollateralFor(_amount.add(_flashloanFee), false) .mul(flashCloseF.a) .div(flashCloseF.b); // TODO: Get => corresponding amount of BaseProtocol Debt and FujiDebt // Repay BaseProtocol debt IVault(_vault).payback(int256(_amount)); //TODO: Transfer corresponding Debt Amount to Fuji Treasury // Full close if (_amount == userDebtBalance) { f1155.burn(_userAddr, vAssets.collateralID, userCollateral); // Withdraw Full collateral IVault(_vault).withdraw(int256(userCollateral)); // Send unUsed Collateral to User IERC20(vAssets.collateralAsset).univTransfer( _userAddr, userCollateral.sub(userCollateralInPlay) ); } else { f1155.burn(_userAddr, vAssets.collateralID, userCollateralInPlay); // Withdraw Collateral in play Only IVault(_vault).withdraw(int256(userCollateralInPlay)); } // Swap Collateral for underlying to repay Flashloan uint256 remaining = _swap(vAssets.borrowAsset, _amount.add(_flashloanFee), userCollateralInPlay); // Send FlashClose Fee to FujiTreasury IERC20(vAssets.collateralAsset).univTransfer(_fujiAdmin.getTreasury(), remaining); // Send flasher the underlying to repay Flashloan IERC20(vAssets.borrowAsset).univTransfer( payable(_fujiAdmin.getFlasher()), _amount.add(_flashloanFee) ); // Burn Debt f1155 tokens f1155.burn(_userAddr, vAssets.borrowID, _amount); emit FlashClose(_userAddr, vAssets.borrowAsset, userDebtBalance); } /** * @dev Initiates a flashloan to liquidate array of undercollaterized debt positions, * gets bonus (bonusFlashL in Vault) * @param _userAddrs: Array of Address whose position is liquidatable * @param _vault: The vault address where the debt position exist. * @param _flashnum: integer identifier of flashloan provider */ function flashBatchLiquidate( address[] calldata _userAddrs, address _vault, uint8 _flashnum ) external isValidVault(_vault) nonReentrant { // Update Balances at FujiERC1155 IVault(_vault).updateF1155Balances(); // Create Instance of FujiERC1155 IFujiERC1155Ext f1155 = IFujiERC1155Ext(IVault(_vault).fujiERC1155()); // Struct Instance to get Vault Asset IDs in f1155 IVaultExt.VaultAssets memory vAssets = IVaultExt(_vault).vAssets(); address[] memory formattedUserAddrs = new address[](2 * _userAddrs.length); uint256[] memory formattedIds = new uint256[](2 * _userAddrs.length); // Build the required Arrays to query balanceOfBatch from f1155 for (uint256 i = 0; i < _userAddrs.length; i++) { formattedUserAddrs[2 * i] = _userAddrs[i]; formattedUserAddrs[2 * i + 1] = _userAddrs[i]; formattedIds[2 * i] = vAssets.collateralID; formattedIds[2 * i + 1] = vAssets.borrowID; } // Get user Collateral and Debt Balances uint256[] memory usrsBals = f1155.balanceOfBatch(formattedUserAddrs, formattedIds); uint256 neededCollateral; uint256 debtBalanceTotal; for (uint256 i = 0; i < formattedUserAddrs.length; i += 2) { // Compute Amount of Minimum Collateral Required including factors neededCollateral = IVault(_vault).getNeededCollateralFor(usrsBals[i + 1], true); // Check if User is liquidatable if (usrsBals[i] < neededCollateral) { // If true, add User debt balance to the total balance to be liquidated debtBalanceTotal = debtBalanceTotal.add(usrsBals[i + 1]); } else { // Replace User that is not liquidatable by Zero Address formattedUserAddrs[i] = address(0); formattedUserAddrs[i + 1] = address(0); } } // Check there is at least one user liquidatable require(debtBalanceTotal > 0, Errors.VL_USER_NOT_LIQUIDATABLE); Flasher flasher = Flasher(payable(_fujiAdmin.getFlasher())); FlashLoan.Info memory info = FlashLoan.Info({ callType: FlashLoan.CallType.BatchLiquidate, asset: vAssets.borrowAsset, amount: debtBalanceTotal, vault: _vault, newProvider: address(0), userAddrs: formattedUserAddrs, userBalances: usrsBals, userliquidator: msg.sender, fliquidator: address(this) }); flasher.initiateFlashloan(info, _flashnum); } /** * @dev Liquidate a debt position by using a flashloan * @param _userAddrs: array **See formattedUserAddrs construction in 'function flashBatchLiquidate' * @param _usrsBals: array **See construction in 'function flashBatchLiquidate' * @param _liquidatorAddr: liquidator address * @param _vault: Vault address * @param _amount: amount of debt to be repaid * @param _flashloanFee: amount extra charged by flashloan provider * Emits a {FlashLiquidate} event. */ function executeFlashBatchLiquidation( address[] calldata _userAddrs, uint256[] calldata _usrsBals, address _liquidatorAddr, address _vault, uint256 _amount, uint256 _flashloanFee ) external onlyFlash { // Create Instance of FujiERC1155 IFujiERC1155 f1155 = IFujiERC1155(IVault(_vault).fujiERC1155()); // Struct Instance to get Vault Asset IDs in f1155 IVaultExt.VaultAssets memory vAssets = IVaultExt(_vault).vAssets(); // TODO: Get => corresponding amount of BaseProtocol Debt and FujiDebt // TODO: Transfer corresponding Debt Amount to Fuji Treasury // Repay BaseProtocol debt to release collateral IVault(_vault).payback(int256(_amount)); // Compute the Liquidator Bonus bonusFlashL uint256 globalBonus = IVault(_vault).getLiquidationBonusFor(_amount, true); // Compute how much collateral needs to be swapt for all liquidated Users uint256 globalCollateralInPlay = _getCollateralInPlay(vAssets.borrowAsset, _amount.add(_flashloanFee).add(globalBonus)); // Burn Collateral f1155 tokens for each liquidated user _burnMultiLoop(_userAddrs, _usrsBals, IVault(_vault), f1155, vAssets); // Withdraw collateral IVault(_vault).withdraw(int256(globalCollateralInPlay)); _swap(vAssets.borrowAsset, _amount.add(_flashloanFee).add(globalBonus), globalCollateralInPlay); // Send flasher the underlying to repay Flashloan IERC20(vAssets.borrowAsset).univTransfer( payable(_fujiAdmin.getFlasher()), _amount.add(_flashloanFee) ); // Transfer Bonus bonusFlashL to liquidator, minus FlashloanFee convenience IERC20(vAssets.borrowAsset).univTransfer( payable(_liquidatorAddr), globalBonus.sub(_flashloanFee) ); // Burn Debt f1155 tokens and Emit Liquidation Event for Each Liquidated User for (uint256 i = 0; i < _userAddrs.length; i += 2) { if (_userAddrs[i] != address(0)) { f1155.burn(_userAddrs[i], vAssets.borrowID, _usrsBals[i + 1]); emit FlashLiquidate(_userAddrs[i], _liquidatorAddr, vAssets.borrowAsset, _usrsBals[i + 1]); } } } /** * @dev Swap an amount of underlying * @param _borrowAsset: Address of vault borrowAsset * @param _amountToReceive: amount of underlying to receive * @param _collateralAmount: collateral Amount sent for swap */ function _swap( address _borrowAsset, uint256 _amountToReceive, uint256 _collateralAmount ) internal returns (uint256) { // Swap Collateral Asset to Borrow Asset address[] memory path = new address[](2); path[0] = swapper.WETH(); path[1] = _borrowAsset; uint256[] memory swapperAmounts = swapper.swapETHForExactTokens{ value: _collateralAmount }( _amountToReceive, path, address(this), // solhint-disable-next-line block.timestamp ); return _collateralAmount.sub(swapperAmounts[0]); } /** * @dev Get exact amount of collateral to be swapt * @param _borrowAsset: Address of vault borrowAsset * @param _amountToReceive: amount of underlying to receive */ function _getCollateralInPlay(address _borrowAsset, uint256 _amountToReceive) internal view returns (uint256) { address[] memory path = new address[](2); path[0] = swapper.WETH(); path[1] = _borrowAsset; uint256[] memory amounts = swapper.getAmountsIn(_amountToReceive, path); return amounts[0]; } /** * @dev Abstracted function to perform MultBatch Burn of Collateral in Batch Liquidation * checking bonus paid to liquidator by each * See "function executeFlashBatchLiquidation" */ function _burnMultiLoop( address[] memory _userAddrs, uint256[] memory _usrsBals, IVault _vault, IFujiERC1155 _f1155, IVaultExt.VaultAssets memory _vAssets ) internal { uint256 bonusPerUser; uint256 collateralInPlayPerUser; for (uint256 i = 0; i < _userAddrs.length; i += 2) { if (_userAddrs[i] != address(0)) { bonusPerUser = _vault.getLiquidationBonusFor(_usrsBals[i + 1], true); collateralInPlayPerUser = _getCollateralInPlay( _vAssets.borrowAsset, _usrsBals[i + 1].add(bonusPerUser) ); _f1155.burn(_userAddrs[i], _vAssets.collateralID, collateralInPlayPerUser); } } } // Administrative functions /** * @dev Set Factors "a" and "b" for a Struct Factor flashcloseF * For flashCloseF; should be > 1, a/b * @param _newFactorA: A number * @param _newFactorB: A number */ function setFlashCloseFee(uint64 _newFactorA, uint64 _newFactorB) external isAuthorized { flashCloseF.a = _newFactorA; flashCloseF.b = _newFactorB; } /** * @dev Sets the fujiAdmin Address * @param _newFujiAdmin: FujiAdmin Contract Address */ function setFujiAdmin(address _newFujiAdmin) external isAuthorized { _fujiAdmin = IFujiAdmin(_newFujiAdmin); } /** * @dev Changes the Swapper contract address * @param _newSwapper: address of new swapper contract */ function setSwapper(address _newSwapper) external isAuthorized { swapper = IUniswapV2Router02(_newSwapper); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.12; pragma experimental ABIEncoderV2; interface IVault { // Events // Log Users Deposit event Deposit(address indexed userAddrs, address indexed asset, uint256 amount); // Log Users withdraw event Withdraw(address indexed userAddrs, address indexed asset, uint256 amount); // Log Users borrow event Borrow(address indexed userAddrs, address indexed asset, uint256 amount); // Log Users debt repay event Payback(address indexed userAddrs, address indexed asset, uint256 amount); // Log New active provider event SetActiveProvider(address providerAddr); // Log Switch providers event Switch( address vault, address fromProviderAddrs, address toProviderAddr, uint256 debtamount, uint256 collattamount ); // Core Vault Functions function deposit(uint256 _collateralAmount) external payable; function withdraw(int256 _withdrawAmount) external; function borrow(uint256 _borrowAmount) external; function payback(int256 _repayAmount) external payable; function executeSwitch( address _newProvider, uint256 _flashLoanDebt, uint256 _fee ) external; //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 getNeededCollateralFor(uint256 _amount, bool _withFactors) external view returns (uint256); function getLiquidationBonusFor(uint256 _amount, bool _flash) 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; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.12 <0.8.0; interface IFujiAdmin { 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 getaWhiteList() external view returns (address); function getVaultHarvester() external view returns (address); function getBonusFlashL() external view returns (uint64, uint64); function getBonusLiq() external view returns (uint64, uint64); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.12; pragma experimental ABIEncoderV2; 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, bytes memory _data ) 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.6.0 <0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.12 <0.8.0; pragma experimental ABIEncoderV2; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; import { UniERC20 } from "../Libraries/LibUniERC20.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IFujiAdmin } from "../IFujiAdmin.sol"; import { Errors } from "../Libraries/Errors.sol"; import { ILendingPool, IFlashLoanReceiver } from "./AaveFlashLoans.sol"; import { Actions, Account, DyDxFlashloanBase, ICallee, ISoloMargin } from "./DyDxFlashLoans.sol"; import { ICTokenFlashloan, ICFlashloanReceiver } from "./CreamFlashLoans.sol"; import { FlashLoan } from "./LibFlashLoan.sol"; import { IVault } from "../Vaults/IVault.sol"; interface IFliquidator { function executeFlashClose( address _userAddr, address _vault, uint256 _amount, uint256 _flashloanfee ) external; function executeFlashBatchLiquidation( address[] calldata _userAddrs, uint256[] calldata _usrsBals, address _liquidatorAddr, address _vault, uint256 _amount, uint256 _flashloanFee ) external; } interface IFujiMappings { function addressMapping(address) external view returns (address); } contract Flasher is DyDxFlashloanBase, IFlashLoanReceiver, ICFlashloanReceiver, ICallee, Ownable { using SafeMath for uint256; using UniERC20 for IERC20; IFujiAdmin private _fujiAdmin; address private immutable _aaveLendingPool = 0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9; address private immutable _dydxSoloMargin = 0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e; IFujiMappings private immutable _crMappings = IFujiMappings(0x03BD587Fe413D59A20F32Fc75f31bDE1dD1CD6c9); receive() external payable {} modifier isAuthorized() { require( msg.sender == _fujiAdmin.getController() || msg.sender == _fujiAdmin.getFliquidator() || msg.sender == owner(), Errors.VL_NOT_AUTHORIZED ); _; } /** * @dev Sets the fujiAdmin Address * @param _newFujiAdmin: FujiAdmin Contract Address */ function setFujiAdmin(address _newFujiAdmin) public onlyOwner { _fujiAdmin = IFujiAdmin(_newFujiAdmin); } /** * @dev Routing Function for Flashloan Provider * @param info: struct information for flashLoan * @param _flashnum: integer identifier of flashloan provider */ function initiateFlashloan(FlashLoan.Info calldata info, uint8 _flashnum) external isAuthorized { if (_flashnum == 0) { _initiateAaveFlashLoan(info); } else if (_flashnum == 1) { _initiateDyDxFlashLoan(info); } else if (_flashnum == 2) { _initiateCreamFlashLoan(info); } } // ===================== DyDx FlashLoan =================================== /** * @dev Initiates a DyDx flashloan. * @param info: data to be passed between functions executing flashloan logic */ function _initiateDyDxFlashLoan(FlashLoan.Info calldata info) internal { ISoloMargin solo = ISoloMargin(_dydxSoloMargin); // Get marketId from token address uint256 marketId = _getMarketIdFromTokenAddress(solo, info.asset); // 1. Withdraw $ // 2. Call callFunction(...) // 3. Deposit back $ Actions.ActionArgs[] memory operations = new Actions.ActionArgs[](3); operations[0] = _getWithdrawAction(marketId, info.amount); // Encode FlashLoan.Info for callFunction operations[1] = _getCallAction(abi.encode(info)); // add fee of 2 wei operations[2] = _getDepositAction(marketId, info.amount.add(2)); Account.Info[] memory accountInfos = new Account.Info[](1); accountInfos[0] = _getAccountInfo(address(this)); solo.operate(accountInfos, operations); } /** * @dev Executes DyDx Flashloan, this operation is required * and called by Solo when sending loaned amount * @param sender: Not used * @param account: Not used */ function callFunction( address sender, Account.Info calldata account, bytes calldata data ) external override { require(msg.sender == _dydxSoloMargin && sender == address(this), Errors.VL_NOT_AUTHORIZED); account; FlashLoan.Info memory info = abi.decode(data, (FlashLoan.Info)); //Estimate flashloan payback + premium fee of 2 wei, uint256 amountOwing = info.amount.add(2); // Transfer to Vault the flashloan Amount IERC20(info.asset).uniTransfer(payable(info.vault), info.amount); if (info.callType == FlashLoan.CallType.Switch) { IVault(info.vault).executeSwitch(info.newProvider, info.amount, 2); } else if (info.callType == FlashLoan.CallType.Close) { IFliquidator(info.fliquidator).executeFlashClose( info.userAddrs[0], info.vault, info.amount, 2 ); } else { IFliquidator(info.fliquidator).executeFlashBatchLiquidation( info.userAddrs, info.userBalances, info.userliquidator, info.vault, info.amount, 2 ); } //Approve DYDXSolo to spend to repay flashloan IERC20(info.asset).approve(_dydxSoloMargin, amountOwing); } // ===================== Aave FlashLoan =================================== /** * @dev Initiates an Aave flashloan. * @param info: data to be passed between functions executing flashloan logic */ function _initiateAaveFlashLoan(FlashLoan.Info calldata info) internal { //Initialize Instance of Aave Lending Pool ILendingPool aaveLp = ILendingPool(_aaveLendingPool); //Passing arguments to construct Aave flashloan -limited to 1 asset type for now. address receiverAddress = address(this); address[] memory assets = new address[](1); assets[0] = address(info.asset); uint256[] memory amounts = new uint256[](1); amounts[0] = info.amount; // 0 = no debt, 1 = stable, 2 = variable uint256[] memory modes = new uint256[](1); //modes[0] = 0; //address onBehalfOf = address(this); //bytes memory params = abi.encode(info); //uint16 referralCode = 0; //Aave Flashloan initiated. aaveLp.flashLoan(receiverAddress, assets, amounts, modes, address(this), abi.encode(info), 0); } /** * @dev Executes Aave Flashloan, this operation is required * and called by Aaveflashloan when sending loaned amount */ function executeOperation( address[] calldata assets, uint256[] calldata amounts, uint256[] calldata premiums, address initiator, bytes calldata params ) external override returns (bool) { require(msg.sender == _aaveLendingPool && initiator == address(this), Errors.VL_NOT_AUTHORIZED); FlashLoan.Info memory info = abi.decode(params, (FlashLoan.Info)); //Estimate flashloan payback + premium fee, uint256 amountOwing = amounts[0].add(premiums[0]); // Transfer to the vault ERC20 IERC20(assets[0]).uniTransfer(payable(info.vault), amounts[0]); if (info.callType == FlashLoan.CallType.Switch) { IVault(info.vault).executeSwitch(info.newProvider, amounts[0], premiums[0]); } else if (info.callType == FlashLoan.CallType.Close) { IFliquidator(info.fliquidator).executeFlashClose( info.userAddrs[0], info.vault, amounts[0], premiums[0] ); } else { IFliquidator(info.fliquidator).executeFlashBatchLiquidation( info.userAddrs, info.userBalances, info.userliquidator, info.vault, amounts[0], premiums[0] ); } //Approve aaveLP to spend to repay flashloan IERC20(assets[0]).uniApprove(payable(_aaveLendingPool), amountOwing); return true; } // ===================== CreamFinance FlashLoan =================================== /** * @dev Initiates an CreamFinance flashloan. * @param info: data to be passed between functions executing flashloan logic */ function _initiateCreamFlashLoan(FlashLoan.Info calldata info) internal { // Get crToken Address for Flashloan Call address crToken = _crMappings.addressMapping(info.asset); // Prepara data for flashloan execution bytes memory params = abi.encode(info); // Initialize Instance of Cream crLendingContract ICTokenFlashloan(crToken).flashLoan(address(this), info.amount, params); } /** * @dev Executes CreamFinance Flashloan, this operation is required * and called by CreamFinanceflashloan when sending loaned amount */ function executeOperation( address sender, address underlying, uint256 amount, uint256 fee, bytes calldata params ) external override { // Check Msg. Sender is crToken Lending Contract address crToken = _crMappings.addressMapping(underlying); require(msg.sender == crToken && address(this) == sender, Errors.VL_NOT_AUTHORIZED); require(IERC20(underlying).balanceOf(address(this)) >= amount, Errors.VL_FLASHLOAN_FAILED); FlashLoan.Info memory info = abi.decode(params, (FlashLoan.Info)); // Estimate flashloan payback + premium fee, uint256 amountOwing = amount.add(fee); // Transfer to the vault ERC20 IERC20(underlying).uniTransfer(payable(info.vault), amount); // Do task according to CallType if (info.callType == FlashLoan.CallType.Switch) { IVault(info.vault).executeSwitch(info.newProvider, amount, fee); } else if (info.callType == FlashLoan.CallType.Close) { IFliquidator(info.fliquidator).executeFlashClose(info.userAddrs[0], info.vault, amount, fee); } else { IFliquidator(info.fliquidator).executeFlashBatchLiquidation( info.userAddrs, info.userBalances, info.userliquidator, info.vault, amount, fee ); } // Transfer flashloan + fee back to crToken Lending Contract IERC20(underlying).uniTransfer(payable(crToken), amountOwing); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.25 <0.7.5; library FlashLoan { /** * @dev Used to determine which vault's function to call post-flashloan: * - Switch for executeSwitch(...) * - Close for executeFlashClose(...) * - Liquidate for executeFlashLiquidation(...) * - BatchLiquidate for executeFlashBatchLiquidation(...) */ enum CallType { Switch, Close, BatchLiquidate } /** * @dev Struct of params to be passed between functions executing flashloan logic * @param asset: Address of asset to be borrowed with flashloan * @param amount: Amount of asset to be borrowed with flashloan * @param vault: Vault's address on which the flashloan logic to be executed * @param newProvider: New provider's address. Used when callType is Switch * @param userAddrs: User's address array Used when callType is BatchLiquidate * @param userBals: Array of user's balances, Used when callType is BatchLiquidate * @param userliquidator: The user's address who is performing liquidation. Used when callType is Liquidate * @param fliquidator: Fujis Liquidator's address. */ struct Info { CallType callType; address asset; uint256 amount; address vault; address newProvider; address[] userAddrs; uint256[] userBalances; address userliquidator; address fliquidator; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
// SPDX-License-Identifier: agpl-3.0 pragma solidity <0.8.0; /** * @title Errors library * @author Fuji * @notice Defines the error messages emitted by the different contracts of the Aave protocol * @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 MATH_DIVISION_BY_ZERO = "201"; string public constant MATH_ADDITION_OVERFLOW = "202"; string public constant MATH_MULTIPLICATION_OVERFLOW = "203"; string public constant RF_NO_GREENLIGHT = "300"; // Conditions for refinancing are not met, greenLight, deltaAPRThreshold, deltatimestampThreshold 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_CHECK_RATES_FALSE = "302"; //Check Rates routine returned False string public constant VLT_CALLER_MUST_BE_VAULT = "401"; // The caller of this function must be a vault string public constant SP_ALPHA_WHITELIST = "901"; // One ETH cap value for Alpha Version < 1 ETH }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; library LibUniversalERC20 { using SafeERC20 for IERC20; IERC20 private constant _ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); IERC20 private constant _ZERO_ADDRESS = IERC20(0); function isETH(IERC20 token) internal pure returns (bool) { return (token == _ZERO_ADDRESS || token == _ETH_ADDRESS); } function univBalanceOf(IERC20 token, address account) internal view returns (uint256) { if (isETH(token)) { return account.balance; } else { return token.balanceOf(account); } } function univTransfer( IERC20 token, address payable to, uint256 amount ) internal { if (amount > 0) { if (isETH(token)) { (bool sent, ) = to.call{ value: amount }(""); require(sent, "Failed to send Ether"); } else { token.safeTransfer(to, amount); } } } function univApprove( IERC20 token, address to, uint256 amount ) internal { require(!isETH(token), "Approve called on ETH"); 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); } } } }
pragma solidity >=0.6.2; import './IUniswapV2Router01.sol'; interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, address to, uint deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () internal { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; library UniERC20 { using SafeERC20 for IERC20; IERC20 private constant _ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); IERC20 private constant _ZERO_ADDRESS = IERC20(0); function isETH(IERC20 token) internal pure returns (bool) { return (token == _ZERO_ADDRESS || token == _ETH_ADDRESS); } function uniBalanceOf(IERC20 token, address account) internal view returns (uint256) { if (isETH(token)) { return account.balance; } else { return token.balanceOf(account); } } function uniTransfer( IERC20 token, address payable to, uint256 amount ) internal { if (amount > 0) { if (isETH(token)) { to.transfer(amount); } else { token.safeTransfer(to, amount); } } } function uniApprove( IERC20 token, address to, uint256 amount ) internal { require(!isETH(token), "Approve called on ETH"); 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 pragma solidity >=0.4.25 <0.7.5; interface IFlashLoanReceiver { function executeOperation( address[] calldata assets, uint256[] calldata amounts, uint256[] calldata premiums, address initiator, bytes calldata params ) external returns (bool); } interface ILendingPool { function flashLoan( address receiverAddress, address[] calldata assets, uint256[] calldata amounts, uint256[] calldata modes, address onBehalfOf, bytes calldata params, uint16 referralCode ) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.25 <0.7.5; pragma experimental ABIEncoderV2; library Account { enum Status { Normal, Liquid, Vapor } struct Info { address owner; // The address that owns the account uint256 number; // A nonce that allows a single address to control many accounts } } library Actions { enum ActionType { Deposit, // supply tokens Withdraw, // borrow tokens Transfer, // transfer balance between accounts Buy, // buy an amount of some token (publicly) Sell, // sell an amount of some token (publicly) Trade, // trade tokens against another account Liquidate, // liquidate an undercollateralized or expiring account Vaporize, // use excess tokens to zero-out a completely negative account Call // send arbitrary data to an address } struct ActionArgs { ActionType actionType; uint256 accountId; Types.AssetAmount amount; uint256 primaryMarketId; uint256 secondaryMarketId; address otherAddress; uint256 otherAccountId; bytes data; } } library Types { enum AssetDenomination { Wei, // the amount is denominated in wei Par // the amount is denominated in par } enum AssetReference { Delta, // the amount is given as a delta from the current value Target // the amount is given as an exact number to end up at } struct AssetAmount { bool sign; // true if positive AssetDenomination denomination; AssetReference ref; uint256 value; } } /** * @title ICallee * @author dYdX * * Interface that Callees for Solo must implement in order to ingest data. */ interface ICallee { /** * Allows users to send this contract arbitrary data. * * @param sender The msg.sender to Solo * @param accountInfo The account from which the data is being sent * @param data Arbitrary data given by the sender */ function callFunction( address sender, Account.Info memory accountInfo, bytes memory data ) external; } interface ISoloMargin { function getNumMarkets() external view returns (uint256); function getMarketTokenAddress(uint256 marketId) external view returns (address); function operate(Account.Info[] memory accounts, Actions.ActionArgs[] memory actions) external; } contract DyDxFlashloanBase { // -- Internal Helper functions -- // function _getMarketIdFromTokenAddress(ISoloMargin solo, address token) internal view returns (uint256) { uint256 numMarkets = solo.getNumMarkets(); address curToken; for (uint256 i = 0; i < numMarkets; i++) { curToken = solo.getMarketTokenAddress(i); if (curToken == token) { return i; } } revert("No marketId found"); } function _getAccountInfo(address receiver) internal pure returns (Account.Info memory) { return Account.Info({ owner: receiver, number: 1 }); } function _getWithdrawAction(uint256 marketId, uint256 amount) internal view returns (Actions.ActionArgs memory) { return Actions.ActionArgs({ actionType: Actions.ActionType.Withdraw, accountId: 0, amount: Types.AssetAmount({ sign: false, denomination: Types.AssetDenomination.Wei, ref: Types.AssetReference.Delta, value: amount }), primaryMarketId: marketId, secondaryMarketId: 0, otherAddress: address(this), otherAccountId: 0, data: "" }); } function _getCallAction(bytes memory data) internal view returns (Actions.ActionArgs memory) { return Actions.ActionArgs({ actionType: Actions.ActionType.Call, accountId: 0, amount: Types.AssetAmount({ sign: false, denomination: Types.AssetDenomination.Wei, ref: Types.AssetReference.Delta, value: 0 }), primaryMarketId: 0, secondaryMarketId: 0, otherAddress: address(this), otherAccountId: 0, data: data }); } function _getDepositAction(uint256 marketId, uint256 amount) internal view returns (Actions.ActionArgs memory) { return Actions.ActionArgs({ actionType: Actions.ActionType.Deposit, accountId: 0, amount: Types.AssetAmount({ sign: true, denomination: Types.AssetDenomination.Wei, ref: Types.AssetReference.Delta, value: amount }), primaryMarketId: marketId, secondaryMarketId: 0, otherAddress: address(this), otherAccountId: 0, data: "" }); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.25 <0.7.5; interface ICFlashloanReceiver { function executeOperation( address sender, address underlying, uint256 amount, uint256 fee, bytes calldata params ) external; } interface ICTokenFlashloan { function flashLoan( address receiver, uint256 amount, bytes calldata params ) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./IERC20.sol"; import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
pragma solidity >=0.6.2; interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityETH( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityETHWithPermit( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); }
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "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":"userAddr","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FlashClose","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddr","type":"address"},{"indexed":false,"internalType":"address","name":"liquidator","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FlashLiquidate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userAddr","type":"address"},{"indexed":false,"internalType":"address","name":"liquidator","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Liquidate","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"},{"inputs":[{"internalType":"address[]","name":"_userAddrs","type":"address[]"},{"internalType":"address","name":"_vault","type":"address"}],"name":"batchLiquidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_userAddrs","type":"address[]"},{"internalType":"uint256[]","name":"_usrsBals","type":"uint256[]"},{"internalType":"address","name":"_liquidatorAddr","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_flashloanFee","type":"uint256"}],"name":"executeFlashBatchLiquidation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_userAddr","type":"address"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_flashloanFee","type":"uint256"}],"name":"executeFlashClose","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_userAddrs","type":"address[]"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"uint8","name":"_flashnum","type":"uint8"}],"name":"flashBatchLiquidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"_amount","type":"int256"},{"internalType":"address","name":"_vault","type":"address"},{"internalType":"uint8","name":"_flashnum","type":"uint8"}],"name":"flashClose","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flashCloseF","outputs":[{"internalType":"uint64","name":"a","type":"uint64"},{"internalType":"uint64","name":"b","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_newFactorA","type":"uint64"},{"internalType":"uint64","name":"_newFactorB","type":"uint64"}],"name":"setFlashCloseFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newFujiAdmin","type":"address"}],"name":"setFujiAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newSwapper","type":"address"}],"name":"setSwapper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapper","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060006200001e620000a1565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35060018055600280546103f56001600160401b031990911617600160401b600160801b0319166903e80000000000000000179055620000a5565b3390565b613f5e80620000b56000396000f3fe6080604052600436106100d65760003560e01c806391c154321161007f5780639c82f2a4116100595780639c82f2a4146101fc5780639df97b041461021c578063f2fde38b1461023c578063fae5a8f01461025c576100dd565b806391c154321461019c57806398e1fdb5146101bc5780639c6ce5aa146101dc576100dd565b806356bae453116100b057806356bae45314610152578063715018a6146101725780638da5cb5b14610187576100dd565b80630fd9be71146100e25780632b3297f91461010e5780635003d4b414610130576100dd565b366100dd57005b600080fd5b3480156100ee57600080fd5b506100f761027c565b604051610105929190613e68565b60405180910390f35b34801561011a57600080fd5b5061012361029c565b60405161010591906138f1565b34801561013c57600080fd5b5061015061014b36600461374b565b6102ab565b005b34801561015e57600080fd5b5061015061016d366004613587565b6108fd565b34801561017e57600080fd5b5061015061100c565b34801561019357600080fd5b506101236110a2565b3480156101a857600080fd5b506101506101b73660046134b5565b6110b1565b3480156101c857600080fd5b506101506101d7366004613806565b611137565b3480156101e857600080fd5b506101506101f73660046135f2565b6111e5565b34801561020857600080fd5b506101506102173660046134b5565b6117d2565b34801561022857600080fd5b506101506102373660046134ed565b611858565b34801561024857600080fd5b506101506102573660046134b5565b612017565b34801561026857600080fd5b50610150610277366004613532565b6120e4565b60025467ffffffffffffffff808216916801000000000000000090041682565b6004546001600160a01b031681565b600260015414156102d75760405162461bcd60e51b81526004016102ce90613d07565b60405180910390fd5b6002600155600354604051630f6ec81f60e01b815283916001600160a01b031690630f6ec81f9061030c9084906004016138f1565b60206040518083038186803b15801561032457600080fd5b505afa158015610338573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035c919061372b565b6103785760405162461bcd60e51b81526004016102ce90613c73565b60035460408051637fabc90b60e01b815290516000926001600160a01b031691637fabc90b916004808301926020929190829003018186803b1580156103bd57600080fd5b505afa1580156103d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103f591906134d1565b9050836001600160a01b03166367ac280a6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561043257600080fd5b505af1158015610446573d6000803e3d6000fd5b505050506000846001600160a01b031663acb2d4106040518163ffffffff1660e01b815260040160206040518083038186803b15801561048557600080fd5b505afa158015610499573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104bd91906134d1565b90506104c76133f8565b856001600160a01b031663d8df4ce76040518163ffffffff1660e01b815260040160806040518083038186803b15801561050057600080fd5b505afa158015610514573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105389190613786565b90506000826001600160a01b031662fdd58e3384604001516040518363ffffffff1660e01b815260040161056d92919061395c565b60206040518083038186803b15801561058557600080fd5b505afa158015610599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105bd91906137ee565b6060830151604051627eeac760e11b81529192506000916001600160a01b0386169162fdd58e916105f291339160040161395c565b60206040518083038186803b15801561060a57600080fd5b505afa15801561061e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064291906137ee565b9050600081116040518060400160405280600381526020017f31303600000000000000000000000000000000000000000000000000000000008152509061069c5760405162461bcd60e51b81526004016102ce91906139e1565b506000808a126106ac57896106ae565b815b90506000896001600160a01b03166390d7bfae8360006040518363ffffffff1660e01b81526004016106e1929190613e58565b60206040518083038186803b1580156106f957600080fd5b505afa15801561070d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073191906137ee565b9050808410156040518060400160405280600381526020017f31323400000000000000000000000000000000000000000000000000000000008152509061078b5760405162461bcd60e51b81526004016102ce91906139e1565b506040805160018082528183019092526060916020808301908036833701905050905033816000815181106107bc57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506107e461341f565b604080516101208101909152806001815260200188602001516001600160a01b031681526020018581526020018d6001600160a01b0316815260200160006001600160a01b03168152602001838152602001600067ffffffffffffffff8111801561084e57600080fd5b50604051908082528060200260200182016040528015610878578160200160208202803683370190505b508152600060208201523060409182015251631733602360e21b81529091506001600160a01b038a1690635ccd808c906108b89084908f90600401613d3e565b600060405180830381600087803b1580156108d257600080fd5b505af11580156108e6573d6000803e3d6000fd5b505060018055505050505050505050505050505050565b600354604051630f6ec81f60e01b815283916001600160a01b031690630f6ec81f9061092d9084906004016138f1565b60206040518083038186803b15801561094557600080fd5b505afa158015610959573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097d919061372b565b6109995760405162461bcd60e51b81526004016102ce90613c73565b600260015414156109bc5760405162461bcd60e51b81526004016102ce90613d07565b6002600181905550826001600160a01b03166367ac280a6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156109ff57600080fd5b505af1158015610a13573d6000803e3d6000fd5b505050506000836001600160a01b031663acb2d4106040518163ffffffff1660e01b815260040160206040518083038186803b158015610a5257600080fd5b505afa158015610a66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8a91906134d1565b9050610a946133f8565b846001600160a01b031663d8df4ce76040518163ffffffff1660e01b815260040160806040518083038186803b158015610acd57600080fd5b505afa158015610ae1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b059190613786565b905060606002870267ffffffffffffffff81118015610b2357600080fd5b50604051908082528060200260200182016040528015610b4d578160200160208202803683370190505b50905060606002880267ffffffffffffffff81118015610b6c57600080fd5b50604051908082528060200260200182016040528015610b96578160200160208202803683370190505b50905060005b88811015610ca557898982818110610bb057fe5b9050602002016020810190610bc591906134b5565b838260020281518110610bd457fe5b60200260200101906001600160a01b031690816001600160a01b031681525050898982818110610c0057fe5b9050602002016020810190610c1591906134b5565b838260020260010181518110610c2757fe5b60200260200101906001600160a01b031690816001600160a01b031681525050836040015167ffffffffffffffff16828260020281518110610c6557fe5b602002602001018181525050836060015167ffffffffffffffff16828260020260010181518110610c9257fe5b6020908102919091010152600101610b9c565b506040516313849cfd60e21b81526060906001600160a01b03861690634e1273f490610cd790869086906004016139aa565b60006040518083038186803b158015610cef57600080fd5b505afa158015610d03573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d2b9190810190613696565b905060008060005b8551811015610e86578a6001600160a01b03166390d7bfae858360010181518110610d5a57fe5b602002602001015160016040518363ffffffff1660e01b8152600401610d81929190613e58565b60206040518083038186803b158015610d9957600080fd5b505afa158015610dad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd191906137ee565b925082848281518110610de057fe5b60200260200101511015610e1e57610e17848260010181518110610e0057fe5b602002602001015183612b2290919063ffffffff16565b9150610e7e565b6000868281518110610e2c57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506000868260010181518110610e5d57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b600201610d33565b5060408051808201909152600381526206260760eb1b602082015281610ebf5760405162461bcd60e51b81526004016102ce91906139e1565b5060035460408051637fabc90b60e01b815290516000926001600160a01b031691637fabc90b916004808301926020929190829003018186803b158015610f0557600080fd5b505afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3d91906134d1565b9050610f4761341f565b506040805161012081018252600281526020898101516001600160a01b03908116918301919091528183018590528d811660608301526000608083015260a0820189905260c082018790523360e0830152306101008301529151631733602360e21b81529091831690635ccd808c90610fc69084908f90600401613d3e565b600060405180830381600087803b158015610fe057600080fd5b505af1158015610ff4573d6000803e3d6000fd5b50506001805550505050505050505050505050505050565b611014612b50565b6001600160a01b03166110256110a2565b6001600160a01b03161461104b5760405162461bcd60e51b81526004016102ce90613c07565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b6000546001600160a01b031690565b6110b96110a2565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b815250906111075760405162461bcd60e51b81526004016102ce91906139e1565b506003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b61113f6110a2565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b8152509061118d5760405162461bcd60e51b81526004016102ce91906139e1565b506002805467ffffffffffffffff92831668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9490931667ffffffffffffffff199091161792909216179055565b600360009054906101000a90046001600160a01b03166001600160a01b0316637fabc90b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561123357600080fd5b505afa158015611247573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126b91906134d1565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b815250906112b95760405162461bcd60e51b81526004016102ce91906139e1565b506000836001600160a01b031663acb2d4106040518163ffffffff1660e01b815260040160206040518083038186803b1580156112f557600080fd5b505afa158015611309573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132d91906134d1565b90506113376133f8565b846001600160a01b031663d8df4ce76040518163ffffffff1660e01b815260040160806040518083038186803b15801561137057600080fd5b505afa158015611384573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a89190613786565b6040516319e6e41560e01b81529091506001600160a01b038616906319e6e415906113d79087906004016139d8565b600060405180830381600087803b1580156113f157600080fd5b505af1158015611405573d6000803e3d6000fd5b505060405163c91c860360e01b8152600092506001600160a01b038816915063c91c86039061143b908890600190600401613e58565b60206040518083038186803b15801561145357600080fd5b505afa158015611467573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148b91906137ee565b905060006114b983602001516114b4846114ae898b612b2290919063ffffffff16565b90612b22565b612b54565b905061153e8c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c9250899150889050612cff565b604051630fcc5d5760e31b81526001600160a01b03881690637e62eab89061156a9084906004016139d8565b600060405180830381600087803b15801561158457600080fd5b505af1158015611598573d6000803e3d6000fd5b50505060208401516115b991506115b3846114ae8a8a612b22565b83612e91565b5060035460408051637fabc90b60e01b81529051611657926001600160a01b031691637fabc90b916004808301926020929190829003018186803b15801561160057600080fd5b505afa158015611614573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163891906134d1565b6116428888612b22565b60208601516001600160a01b03169190613058565b611665886116428488613107565b60005b8b8110156117c35760008d8d8381811061167e57fe5b905060200201602081019061169391906134b5565b6001600160a01b0316146117bb57846001600160a01b031663f5298aca8e8e848181106116bc57fe5b90506020020160208101906116d191906134b5565b86606001518e8e866001018181106116e557fe5b905060200201356040518463ffffffff1660e01b815260040161170a9392919061397f565b600060405180830381600087803b15801561172457600080fd5b505af1158015611738573d6000803e3d6000fd5b5050505083602001516001600160a01b03167f3762788b26b933873cc1c56876d4df89b1f9cf6a76749900c19e2d5e6ae0551a8e8e8481811061177757fe5b905060200201602081019061178c91906134b5565b8b8e8e8660010181811061179c57fe5b905060200201356040516117b29392919061391f565b60405180910390a25b600201611668565b50505050505050505050505050565b6117da6110a2565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b815250906118285760405162461bcd60e51b81526004016102ce91906139e1565b506004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600360009054906101000a90046001600160a01b03166001600160a01b0316637fabc90b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156118a657600080fd5b505afa1580156118ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118de91906134d1565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b8152509061192c5760405162461bcd60e51b81526004016102ce91906139e1565b506000836001600160a01b031663acb2d4106040518163ffffffff1660e01b815260040160206040518083038186803b15801561196857600080fd5b505afa15801561197c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a091906134d1565b90506119aa6133f8565b846001600160a01b031663d8df4ce76040518163ffffffff1660e01b815260040160806040518083038186803b1580156119e357600080fd5b505afa1580156119f7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1b9190613786565b90506000826001600160a01b031662fdd58e8884604001516040518363ffffffff1660e01b8152600401611a5092919061395c565b60206040518083038186803b158015611a6857600080fd5b505afa158015611a7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa091906137ee565b6060830151604051627eeac760e11b81529192506000916001600160a01b0386169162fdd58e91611ad5918c9160040161395c565b60206040518083038186803b158015611aed57600080fd5b505afa158015611b01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2591906137ee565b600254909150600090611be39067ffffffffffffffff680100000000000000008204811691611bdd91166001600160a01b038c166390d7bfae611b688d8d612b22565b60006040518363ffffffff1660e01b8152600401611b87929190613e58565b60206040518083038186803b158015611b9f57600080fd5b505afa158015611bb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd791906137ee565b9061312f565b90613169565b6040516319e6e41560e01b81529091506001600160a01b038916906319e6e41590611c12908a906004016139d8565b600060405180830381600087803b158015611c2c57600080fd5b505af1158015611c40573d6000803e3d6000fd5b5050505081871415611d3d576040808501519051637a94c56560e11b81526001600160a01b0387169163f5298aca91611c7f918d91889060040161397f565b600060405180830381600087803b158015611c9957600080fd5b505af1158015611cad573d6000803e3d6000fd5b5050604051630fcc5d5760e31b81526001600160a01b038b169250637e62eab89150611cdd9086906004016139d8565b600060405180830381600087803b158015611cf757600080fd5b505af1158015611d0b573d6000803e3d6000fd5b50505050611d3889611d26838661310790919063ffffffff16565b86516001600160a01b03169190613058565b611e01565b6040808501519051637a94c56560e11b81526001600160a01b0387169163f5298aca91611d70918d91869060040161397f565b600060405180830381600087803b158015611d8a57600080fd5b505af1158015611d9e573d6000803e3d6000fd5b5050604051630fcc5d5760e31b81526001600160a01b038b169250637e62eab89150611dce9084906004016139d8565b600060405180830381600087803b158015611de857600080fd5b505af1158015611dfc573d6000803e3d6000fd5b505050505b6020840151600090611e1d90611e178a8a612b22565b84612e91565b9050611eba600360009054906101000a90046001600160a01b03166001600160a01b0316633b19e84a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611e7057600080fd5b505afa158015611e84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea891906134d1565b86516001600160a01b03169083613058565b60035460408051637fabc90b60e01b81529051611f57926001600160a01b031691637fabc90b916004808301926020929190829003018186803b158015611f0057600080fd5b505afa158015611f14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3891906134d1565b611f428a8a612b22565b60208801516001600160a01b03169190613058565b6060850151604051637a94c56560e11b81526001600160a01b0388169163f5298aca91611f8a918e918d9060040161397f565b600060405180830381600087803b158015611fa457600080fd5b505af1158015611fb8573d6000803e3d6000fd5b5050505084602001516001600160a01b03168a6001600160a01b03167f3eeeaba10d85fe3ba0708f01d644ff55bbdf227dd736ce68eba30cd119514c128560405161200391906139d8565b60405180910390a350505050505050505050565b61201f612b50565b6001600160a01b03166120306110a2565b6001600160a01b0316146120565760405162461bcd60e51b81526004016102ce90613c07565b6001600160a01b03811661207c5760405162461bcd60e51b81526004016102ce90613a14565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600260015414156121075760405162461bcd60e51b81526004016102ce90613d07565b6002600155600354604051630f6ec81f60e01b815282916001600160a01b031690630f6ec81f9061213c9084906004016138f1565b60206040518083038186803b15801561215457600080fd5b505afa158015612168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218c919061372b565b6121a85760405162461bcd60e51b81526004016102ce90613c73565b816001600160a01b03166367ac280a6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156121e357600080fd5b505af11580156121f7573d6000803e3d6000fd5b505050506000826001600160a01b031663acb2d4106040518163ffffffff1660e01b815260040160206040518083038186803b15801561223657600080fd5b505afa15801561224a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226e91906134d1565b90506122786133f8565b836001600160a01b031663d8df4ce76040518163ffffffff1660e01b815260040160806040518083038186803b1580156122b157600080fd5b505afa1580156122c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e99190613786565b905060606002860267ffffffffffffffff8111801561230757600080fd5b50604051908082528060200260200182016040528015612331578160200160208202803683370190505b50905060606002870267ffffffffffffffff8111801561235057600080fd5b5060405190808252806020026020018201604052801561237a578160200160208202803683370190505b50905060005b878110156124895788888281811061239457fe5b90506020020160208101906123a991906134b5565b8382600202815181106123b857fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508888828181106123e457fe5b90506020020160208101906123f991906134b5565b83826002026001018151811061240b57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050836040015167ffffffffffffffff1682826002028151811061244957fe5b602002602001018181525050836060015167ffffffffffffffff1682826002026001018151811061247657fe5b6020908102919091010152600101612380565b506040516313849cfd60e21b81526060906001600160a01b03861690634e1273f4906124bb90869086906004016139aa565b60006040518083038186803b1580156124d357600080fd5b505afa1580156124e7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261250f9190810190613696565b905060008060005b855181101561265357896001600160a01b03166390d7bfae85836001018151811061253e57fe5b602002602001015160016040518363ffffffff1660e01b8152600401612565929190613e58565b60206040518083038186803b15801561257d57600080fd5b505afa158015612591573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b591906137ee565b9250828482815181106125c457fe5b602002602001015110156125eb576125e4848260010181518110610e0057fe5b915061264b565b60008682815181106125f957fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600086826001018151811061262a57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b600201612517565b5060408051808201909152600381526206260760eb1b60208201528161268c5760405162461bcd60e51b81526004016102ce91906139e1565b5060208601516040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815282916001600160a01b03169063dd62ed3e906126da9033903090600401613905565b60206040518083038186803b1580156126f257600080fd5b505afa158015612706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061272a91906137ee565b10156040518060400160405280600381526020017f3130370000000000000000000000000000000000000000000000000000000000815250906127805760405162461bcd60e51b81526004016102ce91906139e1565b5085602001516001600160a01b03166323b872dd3330846040518463ffffffff1660e01b81526004016127b59392919061391f565b602060405180830381600087803b1580156127cf57600080fd5b505af11580156127e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612807919061372b565b506020860151612821906001600160a01b03168a83613058565b6040516319e6e41560e01b81526001600160a01b038a16906319e6e4159061284d9084906004016139d8565b600060405180830381600087803b15801561286757600080fd5b505af115801561287b573d6000803e3d6000fd5b505060405163c91c860360e01b8152600092506001600160a01b038c16915063c91c8603906128b09085908590600401613e58565b60206040518083038186803b1580156128c857600080fd5b505afa1580156128dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061290091906137ee565b9050600061291f88602001516114b48486612b2290919063ffffffff16565b905061292e87868d8c8c612cff565b604051630fcc5d5760e31b81526001600160a01b038c1690637e62eab89061295a9084906004016139d8565b600060405180830381600087803b15801561297457600080fd5b505af1158015612988573d6000803e3d6000fd5b505050602089015161299f91506115b38585612b22565b506129c3336129ae8585612b22565b60208b01516001600160a01b03169190613058565b60005b8751811015612b0e5760006001600160a01b03168882815181106129e657fe5b60200260200101516001600160a01b031614612b0657896001600160a01b031663f5298aca898381518110612a1757fe5b60200260200101518b60600151898560010181518110612a3357fe5b60200260200101516040518463ffffffff1660e01b8152600401612a599392919061397f565b600060405180830381600087803b158015612a7357600080fd5b505af1158015612a87573d6000803e3d6000fd5b5050505088602001516001600160a01b0316888281518110612aa557fe5b60200260200101516001600160a01b03167f033fe6dadd06de536cd7b34266e12610e9d77a23d48d3d6218962a87cb74051433898560010181518110612ae757fe5b6020026020010151604051612afd929190613943565b60405180910390a35b6002016129c6565b505060018055505050505050505050505050565b600082820183811015612b475760405162461bcd60e51b81526004016102ce90613a71565b90505b92915050565b3390565b6040805160028082526060808301845260009390929190602083019080368337505060048054604080516315ab88c960e31b815290519495506001600160a01b039091169363ad5c4648935081830192602092829003018186803b158015612bbb57600080fd5b505afa158015612bcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf391906134d1565b81600081518110612c0057fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508381600181518110612c2e57fe5b6001600160a01b039283166020918202929092010152600480546040517f1f00ca740000000000000000000000000000000000000000000000000000000081526060939190911691631f00ca7491612c8a918891879101613e0a565b60006040518083038186803b158015612ca257600080fd5b505afa158015612cb6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612cde9190810190613696565b905080600081518110612ced57fe5b60200260200101519250505092915050565b60008060005b8751811015612e875760006001600160a01b0316888281518110612d2557fe5b60200260200101516001600160a01b031614612e7f57856001600160a01b031663c91c8603888360010181518110612d5957fe5b602002602001015160016040518363ffffffff1660e01b8152600401612d80929190613e58565b60206040518083038186803b158015612d9857600080fd5b505afa158015612dac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd091906137ee565b9250612e0384602001516114b4858a8560010181518110612ded57fe5b6020026020010151612b2290919063ffffffff16565b9150846001600160a01b031663f5298aca898381518110612e2057fe5b60200260200101518660400151856040518463ffffffff1660e01b8152600401612e4c9392919061397f565b600060405180830381600087803b158015612e6657600080fd5b505af1158015612e7a573d6000803e3d6000fd5b505050505b600201612d05565b5050505050505050565b6040805160028082526060808301845260009390929190602083019080368337505060048054604080516315ab88c960e31b815290519495506001600160a01b039091169363ad5c4648935081830192602092829003018186803b158015612ef857600080fd5b505afa158015612f0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f3091906134d1565b81600081518110612f3d57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508481600181518110612f6b57fe5b6001600160a01b039283166020918202929092010152600480546040517ffb3bdb41000000000000000000000000000000000000000000000000000000008152606093919091169163fb3bdb41918791612fcd918a9188913091429101613e23565b6000604051808303818588803b158015612fe657600080fd5b505af1158015612ffa573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526130239190810190613696565b905061304c8160008151811061303557fe5b60200260200101518561310790919063ffffffff16565b925050505b9392505050565b8015613102576130678361319b565b156130ee576000826001600160a01b031682604051613085906138ee565b60006040518083038185875af1925050503d80600081146130c2576040519150601f19603f3d011682016040523d82523d6000602084013e6130c7565b606091505b50509050806130e85760405162461bcd60e51b81526004016102ce90613aa8565b50613102565b6131026001600160a01b03841683836131d4565b505050565b6000828211156131295760405162461bcd60e51b81526004016102ce90613adf565b50900390565b60008261313e57506000612b4a565b8282028284828161314b57fe5b0414612b475760405162461bcd60e51b81526004016102ce90613baa565b600080821161318a5760405162461bcd60e51b81526004016102ce90613b73565b81838161319357fe5b049392505050565b60006001600160a01b0382161580612b4a57506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b6131028363a9059cbb60e01b84846040516024016131f3929190613943565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915260606132a7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166132e19092919063ffffffff16565b80519091501561310257808060200190518101906132c5919061372b565b6131025760405162461bcd60e51b81526004016102ce90613caa565b60606132f084846000856132f8565b949350505050565b60608247101561331a5760405162461bcd60e51b81526004016102ce90613b16565b613323856133b9565b61333f5760405162461bcd60e51b81526004016102ce90613c3c565b60006060866001600160a01b0316858760405161335c91906138d2565b60006040518083038185875af1925050503d8060008114613399576040519150601f19603f3d011682016040523d82523d6000602084013e61339e565b606091505b50915091506133ae8282866133bf565b979650505050505050565b3b151590565b606083156133ce575081613051565b8251156133de5782518084602001fd5b8160405162461bcd60e51b81526004016102ce91906139e1565b60408051608081018252600080825260208201819052918101829052606081019190915290565b60408051610120810190915280600081526000602082018190526040820181905260608083018290526080830182905260a0830181905260c083015260e082018190526101009091015290565b60008083601f84011261347d578182fd5b50813567ffffffffffffffff811115613494578182fd5b60208301915083602080830285010111156134ae57600080fd5b9250929050565b6000602082840312156134c6578081fd5b8135612b4781613efa565b6000602082840312156134e2578081fd5b8151612b4781613efa565b60008060008060808587031215613502578283fd5b843561350d81613efa565b9350602085013561351d81613efa565b93969395505050506040820135916060013590565b600080600060408486031215613546578283fd5b833567ffffffffffffffff81111561355c578384fd5b6135688682870161346c565b909450925050602084013561357c81613efa565b809150509250925092565b6000806000806060858703121561359c578384fd5b843567ffffffffffffffff8111156135b2578485fd5b6135be8782880161346c565b90955093505060208501356135d281613efa565b9150604085013560ff811681146135e7578182fd5b939692955090935050565b60008060008060008060008060c0898b03121561360d578384fd5b883567ffffffffffffffff80821115613624578586fd5b6136308c838d0161346c565b909a50985060208b0135915080821115613648578586fd5b506136558b828c0161346c565b909750955050604089013561366981613efa565b9350606089013561367981613efa565b979a969950949793969295929450505060808201359160a0013590565b600060208083850312156136a8578182fd5b825167ffffffffffffffff8111156136be578283fd5b8301601f810185136136ce578283fd5b80516136e16136dc82613eaa565b613e83565b81815283810190838501858402850186018910156136fd578687fd5b8694505b8385101561371f578051835260019490940193918501918501613701565b50979650505050505050565b60006020828403121561373c578081fd5b81518015158114612b47578182fd5b60008060006060848603121561375f578081fd5b83359250602084013561377181613efa565b9150604084013560ff8116811461357c578182fd5b600060808284031215613797578081fd5b6137a16080613e83565b82516137ac81613efa565b815260208301516137bc81613efa565b602082015260408301516137cf81613f12565b604082015260608301516137e281613f12565b60608201529392505050565b6000602082840312156137ff578081fd5b5051919050565b60008060408385031215613818578182fd5b823561382381613f12565b9150602083013561383381613f12565b809150509250929050565b6001600160a01b03169052565b6000815180845260208085019450808401835b838110156138835781516001600160a01b03168752958201959082019060010161385e565b509495945050505050565b6000815180845260208085019450808401835b83811015613883578151875295820195908201906001016138a1565b600381106138c757fe5b9052565b60ff169052565b600082516138e4818460208701613eca565b9190910192915050565b90565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392909216825267ffffffffffffffff16602082015260400190565b6001600160a01b0393909316835267ffffffffffffffff919091166020830152604082015260600190565b6000604082526139bd604083018561384b565b82810360208401526139cf818561388e565b95945050505050565b90815260200190565b6000602082528251806020840152613a00816040850160208701613eca565b601f01601f19169190910160400192915050565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201527f6464726573730000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526014908201527f4661696c656420746f2073656e64204574686572000000000000000000000000604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60408201527f722063616c6c0000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60408201527f7700000000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600e908201527f496e76616c6964207661756c7421000000000000000000000000000000000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60408201527f6f74207375636365656400000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b600060408252613d526040830185516138bd565b6020840151613d64606084018261383e565b50604084015160808301526060840151613d8160a084018261383e565b506080840151613d9460c084018261383e565b5060a08401516101208060e0850152613db161016085018361384b565b915060c0860151610100603f198685030181870152613dd0848361388e565b935060e08801519150613de58387018361383e565b8701519150613dfa905061014085018261383e565b50905061305160208301846138cb565b6000838252604060208301526132f0604083018461384b565b600085825260806020830152613e3c608083018661384b565b6001600160a01b03949094166040830152506060015292915050565b9182521515602082015260400190565b67ffffffffffffffff92831681529116602082015260400190565b60405181810167ffffffffffffffff81118282101715613ea257600080fd5b604052919050565b600067ffffffffffffffff821115613ec0578081fd5b5060209081020190565b60005b83811015613ee5578181015183820152602001613ecd565b83811115613ef4576000848401525b50505050565b6001600160a01b0381168114613f0f57600080fd5b50565b67ffffffffffffffff81168114613f0f57600080fdfea2646970667358221220ccc14c143b83cd5b1ace9c4784a779aee158c1f59fde418116ad3f6b75defd0b64736f6c634300060c0033
Deployed Bytecode
0x6080604052600436106100d65760003560e01c806391c154321161007f5780639c82f2a4116100595780639c82f2a4146101fc5780639df97b041461021c578063f2fde38b1461023c578063fae5a8f01461025c576100dd565b806391c154321461019c57806398e1fdb5146101bc5780639c6ce5aa146101dc576100dd565b806356bae453116100b057806356bae45314610152578063715018a6146101725780638da5cb5b14610187576100dd565b80630fd9be71146100e25780632b3297f91461010e5780635003d4b414610130576100dd565b366100dd57005b600080fd5b3480156100ee57600080fd5b506100f761027c565b604051610105929190613e68565b60405180910390f35b34801561011a57600080fd5b5061012361029c565b60405161010591906138f1565b34801561013c57600080fd5b5061015061014b36600461374b565b6102ab565b005b34801561015e57600080fd5b5061015061016d366004613587565b6108fd565b34801561017e57600080fd5b5061015061100c565b34801561019357600080fd5b506101236110a2565b3480156101a857600080fd5b506101506101b73660046134b5565b6110b1565b3480156101c857600080fd5b506101506101d7366004613806565b611137565b3480156101e857600080fd5b506101506101f73660046135f2565b6111e5565b34801561020857600080fd5b506101506102173660046134b5565b6117d2565b34801561022857600080fd5b506101506102373660046134ed565b611858565b34801561024857600080fd5b506101506102573660046134b5565b612017565b34801561026857600080fd5b50610150610277366004613532565b6120e4565b60025467ffffffffffffffff808216916801000000000000000090041682565b6004546001600160a01b031681565b600260015414156102d75760405162461bcd60e51b81526004016102ce90613d07565b60405180910390fd5b6002600155600354604051630f6ec81f60e01b815283916001600160a01b031690630f6ec81f9061030c9084906004016138f1565b60206040518083038186803b15801561032457600080fd5b505afa158015610338573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035c919061372b565b6103785760405162461bcd60e51b81526004016102ce90613c73565b60035460408051637fabc90b60e01b815290516000926001600160a01b031691637fabc90b916004808301926020929190829003018186803b1580156103bd57600080fd5b505afa1580156103d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103f591906134d1565b9050836001600160a01b03166367ac280a6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561043257600080fd5b505af1158015610446573d6000803e3d6000fd5b505050506000846001600160a01b031663acb2d4106040518163ffffffff1660e01b815260040160206040518083038186803b15801561048557600080fd5b505afa158015610499573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104bd91906134d1565b90506104c76133f8565b856001600160a01b031663d8df4ce76040518163ffffffff1660e01b815260040160806040518083038186803b15801561050057600080fd5b505afa158015610514573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105389190613786565b90506000826001600160a01b031662fdd58e3384604001516040518363ffffffff1660e01b815260040161056d92919061395c565b60206040518083038186803b15801561058557600080fd5b505afa158015610599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105bd91906137ee565b6060830151604051627eeac760e11b81529192506000916001600160a01b0386169162fdd58e916105f291339160040161395c565b60206040518083038186803b15801561060a57600080fd5b505afa15801561061e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064291906137ee565b9050600081116040518060400160405280600381526020017f31303600000000000000000000000000000000000000000000000000000000008152509061069c5760405162461bcd60e51b81526004016102ce91906139e1565b506000808a126106ac57896106ae565b815b90506000896001600160a01b03166390d7bfae8360006040518363ffffffff1660e01b81526004016106e1929190613e58565b60206040518083038186803b1580156106f957600080fd5b505afa15801561070d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073191906137ee565b9050808410156040518060400160405280600381526020017f31323400000000000000000000000000000000000000000000000000000000008152509061078b5760405162461bcd60e51b81526004016102ce91906139e1565b506040805160018082528183019092526060916020808301908036833701905050905033816000815181106107bc57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506107e461341f565b604080516101208101909152806001815260200188602001516001600160a01b031681526020018581526020018d6001600160a01b0316815260200160006001600160a01b03168152602001838152602001600067ffffffffffffffff8111801561084e57600080fd5b50604051908082528060200260200182016040528015610878578160200160208202803683370190505b508152600060208201523060409182015251631733602360e21b81529091506001600160a01b038a1690635ccd808c906108b89084908f90600401613d3e565b600060405180830381600087803b1580156108d257600080fd5b505af11580156108e6573d6000803e3d6000fd5b505060018055505050505050505050505050505050565b600354604051630f6ec81f60e01b815283916001600160a01b031690630f6ec81f9061092d9084906004016138f1565b60206040518083038186803b15801561094557600080fd5b505afa158015610959573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097d919061372b565b6109995760405162461bcd60e51b81526004016102ce90613c73565b600260015414156109bc5760405162461bcd60e51b81526004016102ce90613d07565b6002600181905550826001600160a01b03166367ac280a6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156109ff57600080fd5b505af1158015610a13573d6000803e3d6000fd5b505050506000836001600160a01b031663acb2d4106040518163ffffffff1660e01b815260040160206040518083038186803b158015610a5257600080fd5b505afa158015610a66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8a91906134d1565b9050610a946133f8565b846001600160a01b031663d8df4ce76040518163ffffffff1660e01b815260040160806040518083038186803b158015610acd57600080fd5b505afa158015610ae1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b059190613786565b905060606002870267ffffffffffffffff81118015610b2357600080fd5b50604051908082528060200260200182016040528015610b4d578160200160208202803683370190505b50905060606002880267ffffffffffffffff81118015610b6c57600080fd5b50604051908082528060200260200182016040528015610b96578160200160208202803683370190505b50905060005b88811015610ca557898982818110610bb057fe5b9050602002016020810190610bc591906134b5565b838260020281518110610bd457fe5b60200260200101906001600160a01b031690816001600160a01b031681525050898982818110610c0057fe5b9050602002016020810190610c1591906134b5565b838260020260010181518110610c2757fe5b60200260200101906001600160a01b031690816001600160a01b031681525050836040015167ffffffffffffffff16828260020281518110610c6557fe5b602002602001018181525050836060015167ffffffffffffffff16828260020260010181518110610c9257fe5b6020908102919091010152600101610b9c565b506040516313849cfd60e21b81526060906001600160a01b03861690634e1273f490610cd790869086906004016139aa565b60006040518083038186803b158015610cef57600080fd5b505afa158015610d03573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d2b9190810190613696565b905060008060005b8551811015610e86578a6001600160a01b03166390d7bfae858360010181518110610d5a57fe5b602002602001015160016040518363ffffffff1660e01b8152600401610d81929190613e58565b60206040518083038186803b158015610d9957600080fd5b505afa158015610dad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd191906137ee565b925082848281518110610de057fe5b60200260200101511015610e1e57610e17848260010181518110610e0057fe5b602002602001015183612b2290919063ffffffff16565b9150610e7e565b6000868281518110610e2c57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506000868260010181518110610e5d57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b600201610d33565b5060408051808201909152600381526206260760eb1b602082015281610ebf5760405162461bcd60e51b81526004016102ce91906139e1565b5060035460408051637fabc90b60e01b815290516000926001600160a01b031691637fabc90b916004808301926020929190829003018186803b158015610f0557600080fd5b505afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3d91906134d1565b9050610f4761341f565b506040805161012081018252600281526020898101516001600160a01b03908116918301919091528183018590528d811660608301526000608083015260a0820189905260c082018790523360e0830152306101008301529151631733602360e21b81529091831690635ccd808c90610fc69084908f90600401613d3e565b600060405180830381600087803b158015610fe057600080fd5b505af1158015610ff4573d6000803e3d6000fd5b50506001805550505050505050505050505050505050565b611014612b50565b6001600160a01b03166110256110a2565b6001600160a01b03161461104b5760405162461bcd60e51b81526004016102ce90613c07565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b6000546001600160a01b031690565b6110b96110a2565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b815250906111075760405162461bcd60e51b81526004016102ce91906139e1565b506003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b61113f6110a2565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b8152509061118d5760405162461bcd60e51b81526004016102ce91906139e1565b506002805467ffffffffffffffff92831668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9490931667ffffffffffffffff199091161792909216179055565b600360009054906101000a90046001600160a01b03166001600160a01b0316637fabc90b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561123357600080fd5b505afa158015611247573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126b91906134d1565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b815250906112b95760405162461bcd60e51b81526004016102ce91906139e1565b506000836001600160a01b031663acb2d4106040518163ffffffff1660e01b815260040160206040518083038186803b1580156112f557600080fd5b505afa158015611309573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132d91906134d1565b90506113376133f8565b846001600160a01b031663d8df4ce76040518163ffffffff1660e01b815260040160806040518083038186803b15801561137057600080fd5b505afa158015611384573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a89190613786565b6040516319e6e41560e01b81529091506001600160a01b038616906319e6e415906113d79087906004016139d8565b600060405180830381600087803b1580156113f157600080fd5b505af1158015611405573d6000803e3d6000fd5b505060405163c91c860360e01b8152600092506001600160a01b038816915063c91c86039061143b908890600190600401613e58565b60206040518083038186803b15801561145357600080fd5b505afa158015611467573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148b91906137ee565b905060006114b983602001516114b4846114ae898b612b2290919063ffffffff16565b90612b22565b612b54565b905061153e8c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c9250899150889050612cff565b604051630fcc5d5760e31b81526001600160a01b03881690637e62eab89061156a9084906004016139d8565b600060405180830381600087803b15801561158457600080fd5b505af1158015611598573d6000803e3d6000fd5b50505060208401516115b991506115b3846114ae8a8a612b22565b83612e91565b5060035460408051637fabc90b60e01b81529051611657926001600160a01b031691637fabc90b916004808301926020929190829003018186803b15801561160057600080fd5b505afa158015611614573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163891906134d1565b6116428888612b22565b60208601516001600160a01b03169190613058565b611665886116428488613107565b60005b8b8110156117c35760008d8d8381811061167e57fe5b905060200201602081019061169391906134b5565b6001600160a01b0316146117bb57846001600160a01b031663f5298aca8e8e848181106116bc57fe5b90506020020160208101906116d191906134b5565b86606001518e8e866001018181106116e557fe5b905060200201356040518463ffffffff1660e01b815260040161170a9392919061397f565b600060405180830381600087803b15801561172457600080fd5b505af1158015611738573d6000803e3d6000fd5b5050505083602001516001600160a01b03167f3762788b26b933873cc1c56876d4df89b1f9cf6a76749900c19e2d5e6ae0551a8e8e8481811061177757fe5b905060200201602081019061178c91906134b5565b8b8e8e8660010181811061179c57fe5b905060200201356040516117b29392919061391f565b60405180910390a25b600201611668565b50505050505050505050505050565b6117da6110a2565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b815250906118285760405162461bcd60e51b81526004016102ce91906139e1565b506004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600360009054906101000a90046001600160a01b03166001600160a01b0316637fabc90b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156118a657600080fd5b505afa1580156118ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118de91906134d1565b6001600160a01b0316336001600160a01b0316146040518060400160405280600381526020016231313160e81b8152509061192c5760405162461bcd60e51b81526004016102ce91906139e1565b506000836001600160a01b031663acb2d4106040518163ffffffff1660e01b815260040160206040518083038186803b15801561196857600080fd5b505afa15801561197c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a091906134d1565b90506119aa6133f8565b846001600160a01b031663d8df4ce76040518163ffffffff1660e01b815260040160806040518083038186803b1580156119e357600080fd5b505afa1580156119f7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1b9190613786565b90506000826001600160a01b031662fdd58e8884604001516040518363ffffffff1660e01b8152600401611a5092919061395c565b60206040518083038186803b158015611a6857600080fd5b505afa158015611a7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa091906137ee565b6060830151604051627eeac760e11b81529192506000916001600160a01b0386169162fdd58e91611ad5918c9160040161395c565b60206040518083038186803b158015611aed57600080fd5b505afa158015611b01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2591906137ee565b600254909150600090611be39067ffffffffffffffff680100000000000000008204811691611bdd91166001600160a01b038c166390d7bfae611b688d8d612b22565b60006040518363ffffffff1660e01b8152600401611b87929190613e58565b60206040518083038186803b158015611b9f57600080fd5b505afa158015611bb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd791906137ee565b9061312f565b90613169565b6040516319e6e41560e01b81529091506001600160a01b038916906319e6e41590611c12908a906004016139d8565b600060405180830381600087803b158015611c2c57600080fd5b505af1158015611c40573d6000803e3d6000fd5b5050505081871415611d3d576040808501519051637a94c56560e11b81526001600160a01b0387169163f5298aca91611c7f918d91889060040161397f565b600060405180830381600087803b158015611c9957600080fd5b505af1158015611cad573d6000803e3d6000fd5b5050604051630fcc5d5760e31b81526001600160a01b038b169250637e62eab89150611cdd9086906004016139d8565b600060405180830381600087803b158015611cf757600080fd5b505af1158015611d0b573d6000803e3d6000fd5b50505050611d3889611d26838661310790919063ffffffff16565b86516001600160a01b03169190613058565b611e01565b6040808501519051637a94c56560e11b81526001600160a01b0387169163f5298aca91611d70918d91869060040161397f565b600060405180830381600087803b158015611d8a57600080fd5b505af1158015611d9e573d6000803e3d6000fd5b5050604051630fcc5d5760e31b81526001600160a01b038b169250637e62eab89150611dce9084906004016139d8565b600060405180830381600087803b158015611de857600080fd5b505af1158015611dfc573d6000803e3d6000fd5b505050505b6020840151600090611e1d90611e178a8a612b22565b84612e91565b9050611eba600360009054906101000a90046001600160a01b03166001600160a01b0316633b19e84a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611e7057600080fd5b505afa158015611e84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea891906134d1565b86516001600160a01b03169083613058565b60035460408051637fabc90b60e01b81529051611f57926001600160a01b031691637fabc90b916004808301926020929190829003018186803b158015611f0057600080fd5b505afa158015611f14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3891906134d1565b611f428a8a612b22565b60208801516001600160a01b03169190613058565b6060850151604051637a94c56560e11b81526001600160a01b0388169163f5298aca91611f8a918e918d9060040161397f565b600060405180830381600087803b158015611fa457600080fd5b505af1158015611fb8573d6000803e3d6000fd5b5050505084602001516001600160a01b03168a6001600160a01b03167f3eeeaba10d85fe3ba0708f01d644ff55bbdf227dd736ce68eba30cd119514c128560405161200391906139d8565b60405180910390a350505050505050505050565b61201f612b50565b6001600160a01b03166120306110a2565b6001600160a01b0316146120565760405162461bcd60e51b81526004016102ce90613c07565b6001600160a01b03811661207c5760405162461bcd60e51b81526004016102ce90613a14565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600260015414156121075760405162461bcd60e51b81526004016102ce90613d07565b6002600155600354604051630f6ec81f60e01b815282916001600160a01b031690630f6ec81f9061213c9084906004016138f1565b60206040518083038186803b15801561215457600080fd5b505afa158015612168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218c919061372b565b6121a85760405162461bcd60e51b81526004016102ce90613c73565b816001600160a01b03166367ac280a6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156121e357600080fd5b505af11580156121f7573d6000803e3d6000fd5b505050506000826001600160a01b031663acb2d4106040518163ffffffff1660e01b815260040160206040518083038186803b15801561223657600080fd5b505afa15801561224a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226e91906134d1565b90506122786133f8565b836001600160a01b031663d8df4ce76040518163ffffffff1660e01b815260040160806040518083038186803b1580156122b157600080fd5b505afa1580156122c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e99190613786565b905060606002860267ffffffffffffffff8111801561230757600080fd5b50604051908082528060200260200182016040528015612331578160200160208202803683370190505b50905060606002870267ffffffffffffffff8111801561235057600080fd5b5060405190808252806020026020018201604052801561237a578160200160208202803683370190505b50905060005b878110156124895788888281811061239457fe5b90506020020160208101906123a991906134b5565b8382600202815181106123b857fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508888828181106123e457fe5b90506020020160208101906123f991906134b5565b83826002026001018151811061240b57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050836040015167ffffffffffffffff1682826002028151811061244957fe5b602002602001018181525050836060015167ffffffffffffffff1682826002026001018151811061247657fe5b6020908102919091010152600101612380565b506040516313849cfd60e21b81526060906001600160a01b03861690634e1273f4906124bb90869086906004016139aa565b60006040518083038186803b1580156124d357600080fd5b505afa1580156124e7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261250f9190810190613696565b905060008060005b855181101561265357896001600160a01b03166390d7bfae85836001018151811061253e57fe5b602002602001015160016040518363ffffffff1660e01b8152600401612565929190613e58565b60206040518083038186803b15801561257d57600080fd5b505afa158015612591573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b591906137ee565b9250828482815181106125c457fe5b602002602001015110156125eb576125e4848260010181518110610e0057fe5b915061264b565b60008682815181106125f957fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600086826001018151811061262a57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b600201612517565b5060408051808201909152600381526206260760eb1b60208201528161268c5760405162461bcd60e51b81526004016102ce91906139e1565b5060208601516040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815282916001600160a01b03169063dd62ed3e906126da9033903090600401613905565b60206040518083038186803b1580156126f257600080fd5b505afa158015612706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061272a91906137ee565b10156040518060400160405280600381526020017f3130370000000000000000000000000000000000000000000000000000000000815250906127805760405162461bcd60e51b81526004016102ce91906139e1565b5085602001516001600160a01b03166323b872dd3330846040518463ffffffff1660e01b81526004016127b59392919061391f565b602060405180830381600087803b1580156127cf57600080fd5b505af11580156127e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612807919061372b565b506020860151612821906001600160a01b03168a83613058565b6040516319e6e41560e01b81526001600160a01b038a16906319e6e4159061284d9084906004016139d8565b600060405180830381600087803b15801561286757600080fd5b505af115801561287b573d6000803e3d6000fd5b505060405163c91c860360e01b8152600092506001600160a01b038c16915063c91c8603906128b09085908590600401613e58565b60206040518083038186803b1580156128c857600080fd5b505afa1580156128dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061290091906137ee565b9050600061291f88602001516114b48486612b2290919063ffffffff16565b905061292e87868d8c8c612cff565b604051630fcc5d5760e31b81526001600160a01b038c1690637e62eab89061295a9084906004016139d8565b600060405180830381600087803b15801561297457600080fd5b505af1158015612988573d6000803e3d6000fd5b505050602089015161299f91506115b38585612b22565b506129c3336129ae8585612b22565b60208b01516001600160a01b03169190613058565b60005b8751811015612b0e5760006001600160a01b03168882815181106129e657fe5b60200260200101516001600160a01b031614612b0657896001600160a01b031663f5298aca898381518110612a1757fe5b60200260200101518b60600151898560010181518110612a3357fe5b60200260200101516040518463ffffffff1660e01b8152600401612a599392919061397f565b600060405180830381600087803b158015612a7357600080fd5b505af1158015612a87573d6000803e3d6000fd5b5050505088602001516001600160a01b0316888281518110612aa557fe5b60200260200101516001600160a01b03167f033fe6dadd06de536cd7b34266e12610e9d77a23d48d3d6218962a87cb74051433898560010181518110612ae757fe5b6020026020010151604051612afd929190613943565b60405180910390a35b6002016129c6565b505060018055505050505050505050505050565b600082820183811015612b475760405162461bcd60e51b81526004016102ce90613a71565b90505b92915050565b3390565b6040805160028082526060808301845260009390929190602083019080368337505060048054604080516315ab88c960e31b815290519495506001600160a01b039091169363ad5c4648935081830192602092829003018186803b158015612bbb57600080fd5b505afa158015612bcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf391906134d1565b81600081518110612c0057fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508381600181518110612c2e57fe5b6001600160a01b039283166020918202929092010152600480546040517f1f00ca740000000000000000000000000000000000000000000000000000000081526060939190911691631f00ca7491612c8a918891879101613e0a565b60006040518083038186803b158015612ca257600080fd5b505afa158015612cb6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612cde9190810190613696565b905080600081518110612ced57fe5b60200260200101519250505092915050565b60008060005b8751811015612e875760006001600160a01b0316888281518110612d2557fe5b60200260200101516001600160a01b031614612e7f57856001600160a01b031663c91c8603888360010181518110612d5957fe5b602002602001015160016040518363ffffffff1660e01b8152600401612d80929190613e58565b60206040518083038186803b158015612d9857600080fd5b505afa158015612dac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd091906137ee565b9250612e0384602001516114b4858a8560010181518110612ded57fe5b6020026020010151612b2290919063ffffffff16565b9150846001600160a01b031663f5298aca898381518110612e2057fe5b60200260200101518660400151856040518463ffffffff1660e01b8152600401612e4c9392919061397f565b600060405180830381600087803b158015612e6657600080fd5b505af1158015612e7a573d6000803e3d6000fd5b505050505b600201612d05565b5050505050505050565b6040805160028082526060808301845260009390929190602083019080368337505060048054604080516315ab88c960e31b815290519495506001600160a01b039091169363ad5c4648935081830192602092829003018186803b158015612ef857600080fd5b505afa158015612f0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f3091906134d1565b81600081518110612f3d57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508481600181518110612f6b57fe5b6001600160a01b039283166020918202929092010152600480546040517ffb3bdb41000000000000000000000000000000000000000000000000000000008152606093919091169163fb3bdb41918791612fcd918a9188913091429101613e23565b6000604051808303818588803b158015612fe657600080fd5b505af1158015612ffa573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526130239190810190613696565b905061304c8160008151811061303557fe5b60200260200101518561310790919063ffffffff16565b925050505b9392505050565b8015613102576130678361319b565b156130ee576000826001600160a01b031682604051613085906138ee565b60006040518083038185875af1925050503d80600081146130c2576040519150601f19603f3d011682016040523d82523d6000602084013e6130c7565b606091505b50509050806130e85760405162461bcd60e51b81526004016102ce90613aa8565b50613102565b6131026001600160a01b03841683836131d4565b505050565b6000828211156131295760405162461bcd60e51b81526004016102ce90613adf565b50900390565b60008261313e57506000612b4a565b8282028284828161314b57fe5b0414612b475760405162461bcd60e51b81526004016102ce90613baa565b600080821161318a5760405162461bcd60e51b81526004016102ce90613b73565b81838161319357fe5b049392505050565b60006001600160a01b0382161580612b4a57506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b6131028363a9059cbb60e01b84846040516024016131f3929190613943565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915260606132a7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166132e19092919063ffffffff16565b80519091501561310257808060200190518101906132c5919061372b565b6131025760405162461bcd60e51b81526004016102ce90613caa565b60606132f084846000856132f8565b949350505050565b60608247101561331a5760405162461bcd60e51b81526004016102ce90613b16565b613323856133b9565b61333f5760405162461bcd60e51b81526004016102ce90613c3c565b60006060866001600160a01b0316858760405161335c91906138d2565b60006040518083038185875af1925050503d8060008114613399576040519150601f19603f3d011682016040523d82523d6000602084013e61339e565b606091505b50915091506133ae8282866133bf565b979650505050505050565b3b151590565b606083156133ce575081613051565b8251156133de5782518084602001fd5b8160405162461bcd60e51b81526004016102ce91906139e1565b60408051608081018252600080825260208201819052918101829052606081019190915290565b60408051610120810190915280600081526000602082018190526040820181905260608083018290526080830182905260a0830181905260c083015260e082018190526101009091015290565b60008083601f84011261347d578182fd5b50813567ffffffffffffffff811115613494578182fd5b60208301915083602080830285010111156134ae57600080fd5b9250929050565b6000602082840312156134c6578081fd5b8135612b4781613efa565b6000602082840312156134e2578081fd5b8151612b4781613efa565b60008060008060808587031215613502578283fd5b843561350d81613efa565b9350602085013561351d81613efa565b93969395505050506040820135916060013590565b600080600060408486031215613546578283fd5b833567ffffffffffffffff81111561355c578384fd5b6135688682870161346c565b909450925050602084013561357c81613efa565b809150509250925092565b6000806000806060858703121561359c578384fd5b843567ffffffffffffffff8111156135b2578485fd5b6135be8782880161346c565b90955093505060208501356135d281613efa565b9150604085013560ff811681146135e7578182fd5b939692955090935050565b60008060008060008060008060c0898b03121561360d578384fd5b883567ffffffffffffffff80821115613624578586fd5b6136308c838d0161346c565b909a50985060208b0135915080821115613648578586fd5b506136558b828c0161346c565b909750955050604089013561366981613efa565b9350606089013561367981613efa565b979a969950949793969295929450505060808201359160a0013590565b600060208083850312156136a8578182fd5b825167ffffffffffffffff8111156136be578283fd5b8301601f810185136136ce578283fd5b80516136e16136dc82613eaa565b613e83565b81815283810190838501858402850186018910156136fd578687fd5b8694505b8385101561371f578051835260019490940193918501918501613701565b50979650505050505050565b60006020828403121561373c578081fd5b81518015158114612b47578182fd5b60008060006060848603121561375f578081fd5b83359250602084013561377181613efa565b9150604084013560ff8116811461357c578182fd5b600060808284031215613797578081fd5b6137a16080613e83565b82516137ac81613efa565b815260208301516137bc81613efa565b602082015260408301516137cf81613f12565b604082015260608301516137e281613f12565b60608201529392505050565b6000602082840312156137ff578081fd5b5051919050565b60008060408385031215613818578182fd5b823561382381613f12565b9150602083013561383381613f12565b809150509250929050565b6001600160a01b03169052565b6000815180845260208085019450808401835b838110156138835781516001600160a01b03168752958201959082019060010161385e565b509495945050505050565b6000815180845260208085019450808401835b83811015613883578151875295820195908201906001016138a1565b600381106138c757fe5b9052565b60ff169052565b600082516138e4818460208701613eca565b9190910192915050565b90565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392909216825267ffffffffffffffff16602082015260400190565b6001600160a01b0393909316835267ffffffffffffffff919091166020830152604082015260600190565b6000604082526139bd604083018561384b565b82810360208401526139cf818561388e565b95945050505050565b90815260200190565b6000602082528251806020840152613a00816040850160208701613eca565b601f01601f19169190910160400192915050565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201527f6464726573730000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526014908201527f4661696c656420746f2073656e64204574686572000000000000000000000000604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60408201527f722063616c6c0000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60408201527f7700000000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600e908201527f496e76616c6964207661756c7421000000000000000000000000000000000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60408201527f6f74207375636365656400000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b600060408252613d526040830185516138bd565b6020840151613d64606084018261383e565b50604084015160808301526060840151613d8160a084018261383e565b506080840151613d9460c084018261383e565b5060a08401516101208060e0850152613db161016085018361384b565b915060c0860151610100603f198685030181870152613dd0848361388e565b935060e08801519150613de58387018361383e565b8701519150613dfa905061014085018261383e565b50905061305160208301846138cb565b6000838252604060208301526132f0604083018461384b565b600085825260806020830152613e3c608083018661384b565b6001600160a01b03949094166040830152506060015292915050565b9182521515602082015260400190565b67ffffffffffffffff92831681529116602082015260400190565b60405181810167ffffffffffffffff81118282101715613ea257600080fd5b604052919050565b600067ffffffffffffffff821115613ec0578081fd5b5060209081020190565b60005b83811015613ee5578181015183820152602001613ecd565b83811115613ef4576000848401525b50505050565b6001600160a01b0381168114613f0f57600080fd5b50565b67ffffffffffffffff81168114613f0f57600080fdfea2646970667358221220ccc14c143b83cd5b1ace9c4784a779aee158c1f59fde418116ad3f6b75defd0b64736f6c634300060c0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.