Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 14868834 | 870 days ago | IN | 0 ETH | 0.07643959 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
UserModule
Compiler Version
v0.8.6+commit.11564f7e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import "./events.sol"; contract CoreHelpers is Events { using SafeERC20 for IERC20; /** * @dev Update storage. * @notice Internal function to update storage. */ function updateStorage(uint256 exchangePrice_, uint256 newRevenue_) internal { if (exchangePrice_ > _lastRevenueExchangePrice) { _lastRevenueExchangePrice = exchangePrice_; _revenue += newRevenue_; } } /** * @dev Withdraw helper. */ function withdrawHelper(uint256 amount_, uint256 limit_) internal pure returns (uint256, uint256) { uint256 transferAmt_; if (limit_ > amount_) { transferAmt_ = amount_; amount_ = 0; } else { transferAmt_ = limit_; amount_ = amount_ - limit_; } return (amount_, transferAmt_); } /** * @dev Withdraw final. */ function withdrawFinal(uint256 amount_) internal view returns (uint256[] memory transferAmts_) { require(amount_ > 0, "amount-invalid"); ( uint256 tokenCollateralAmt_, , , uint256 tokenVaultBal_, uint256 tokenDSABal_, uint256 netTokenBal_ ) = getVaultBalances(); require(amount_ <= netTokenBal_, "excess-withdrawal"); transferAmts_ = new uint256[](3); if (tokenVaultBal_ > 10) { (amount_, transferAmts_[0]) = withdrawHelper( amount_, tokenVaultBal_ ); } if (tokenDSABal_ > 10 && amount_ > 0) { (amount_, transferAmts_[1]) = withdrawHelper(amount_, tokenDSABal_); } if (tokenCollateralAmt_ > 10 && amount_ > 0) { (amount_, transferAmts_[2]) = withdrawHelper( amount_, tokenCollateralAmt_ ); } } /** * @dev Withdraw related transfers. */ function withdrawTransfers(uint256 amount_, uint256[] memory transferAmts_) internal { if (transferAmts_[0] == amount_) return; uint256 totalTransferAmount_ = transferAmts_[0] + transferAmts_[1] + transferAmts_[2]; require(amount_ == totalTransferAmount_, "transfers-not-valid"); // batching up spells and withdrawing all the required asset from DSA to vault at once uint256 i; uint256 j; uint256 withdrawAmtDSA = transferAmts_[1] + transferAmts_[2]; if (transferAmts_[2] > 0) j++; if (withdrawAmtDSA > 0) j++; string[] memory targets_ = new string[](j); bytes[] memory calldata_ = new bytes[](j); if (transferAmts_[2] > 0) { targets_[i] = "AAVE-V2-A"; calldata_[i] = abi.encodeWithSignature( "withdraw(address,uint256,uint256,uint256)", address(_token), transferAmts_[2], 0, 0 ); i++; } if (withdrawAmtDSA > 0) { targets_[i] = "BASIC-A"; calldata_[i] = abi.encodeWithSignature( "withdraw(address,uint256,address,uint256,uint256)", address(_token), withdrawAmtDSA, address(this), 0, 0 ); } _vaultDsa.cast(targets_, calldata_, address(this)); } /** * @dev Internal function to handle withdrawals. */ function withdrawInternal( uint256 amount_, address to_, bool afterDeleverage_ ) internal returns (uint256 vtokenAmount_) { require(amount_ != 0, "amount cannot be zero"); ( uint256 exchangePrice_, uint256 newRevenue_ ) = getCurrentExchangePrice(); updateStorage(exchangePrice_, newRevenue_); if (amount_ == type(uint256).max) { vtokenAmount_ = balanceOf(msg.sender); amount_ = (vtokenAmount_ * exchangePrice_) / 1e18; } else { vtokenAmount_ = (amount_ * 1e18) / exchangePrice_; } _burn(msg.sender, vtokenAmount_); uint256 fee_ = (amount_ * _withdrawalFee) / 10000; uint256 amountAfterFee_ = amount_ - fee_; uint256[] memory transferAmts_ = withdrawFinal(amountAfterFee_); withdrawTransfers(amountAfterFee_, transferAmts_); (, , , , bool isOk_) = validateFinalPosition(); require(isOk_, "position-risky"); _token.safeTransfer(to_, amountAfterFee_); if (afterDeleverage_) { (, , , bool minGapIsOk_, ) = validateFinalPosition(); require(minGapIsOk_, "excess-deleverage"); } } /** * @dev Internal function for deleverage logics. */ function deleverageInternal(uint256 amt_) internal returns (uint256 transferAmt_) { require(amt_ > 0, "not-valid-amount"); wethContract.safeTransferFrom(msg.sender, address(_vaultDsa), amt_); bool isDsa_ = instaList.accountID(msg.sender) > 0; uint256 i; uint256 j = isDsa_ ? 2 : 3; string[] memory targets_ = new string[](j); bytes[] memory calldata_ = new bytes[](j); targets_[0] = "AAVE-V2-A"; calldata_[0] = abi.encodeWithSignature( "payback(address,uint256,uint256,uint256,uint256)", address(wethContract), amt_, 2, 0, 0 ); if (!isDsa_) { transferAmt_ = amt_ + ((amt_ * _deleverageFee) / 10000); targets_[1] = "AAVE-V2-A"; calldata_[1] = abi.encodeWithSignature( "withdraw(address,uint256,uint256,uint256)", address(stethContract), transferAmt_, 0, 0 ); i = 2; } else { transferAmt_ = amt_; i = 1; } targets_[i] = "BASIC-A"; calldata_[i] = abi.encodeWithSignature( "withdraw(address,uint256,address,uint256,uint256)", isDsa_ ? address(astethToken) : address(stethContract), transferAmt_, msg.sender, 0, 0 ); _vaultDsa.cast(targets_, calldata_, address(this)); } } contract UserModule is CoreHelpers { using SafeERC20 for IERC20; /** * @dev User function to supply. * @param token_ address of token. * @param amount_ amount to supply. * @param to_ address to send vTokens to. * @return vtokenAmount_ amount of vTokens sent to the `to_` address passed */ function supply( address token_, uint256 amount_, address to_ ) external nonReentrant returns (uint256 vtokenAmount_) { require(token_ == address(_token), "wrong token"); require(amount_ != 0, "amount cannot be zero"); ( uint256 exchangePrice_, uint256 newRevenue_ ) = getCurrentExchangePrice(); updateStorage(exchangePrice_, newRevenue_); _token.safeTransferFrom(msg.sender, address(this), amount_); vtokenAmount_ = (amount_ * 1e18) / exchangePrice_; _mint(to_, vtokenAmount_); emit supplyLog(amount_, msg.sender, to_); } /** * @dev User function to withdraw. * @param amount_ amount to withdraw. * @param to_ address to send tokens to. * @return vtokenAmount_ amount of vTokens burnt from caller */ function withdraw(uint256 amount_, address to_) external nonReentrant returns (uint256 vtokenAmount_) { vtokenAmount_ = withdrawInternal(amount_, to_, false); emit withdrawLog(amount_, msg.sender, to_); } /** * @dev If ratio is below then this function will allow anyone to swap from steth -> weth. */ function leverage(uint256 amt_) external nonReentrant { require(amt_ > 0, "not-valid-amount"); stethContract.safeTransferFrom(msg.sender, address(_vaultDsa), amt_); uint256 fee_ = (amt_ * _swapFee) / 10000; uint256 transferAmt_ = amt_ - fee_; _revenueEth += fee_; uint256 tokenBal_ = _token.balanceOf(address(this)); if (tokenBal_ > _tokenMinLimit) _token.safeTransfer(address(_vaultDsa), tokenBal_); tokenBal_ = _token.balanceOf(address(_vaultDsa)); uint256 i; uint256 j = tokenBal_ > _tokenMinLimit ? 4 : 3; string[] memory targets_ = new string[](j); bytes[] memory calldata_ = new bytes[](j); if (tokenBal_ > _tokenMinLimit) { targets_[i] = "AAVE-V2-A"; calldata_[i] = abi.encodeWithSignature( "deposit(address,uint256,uint256,uint256)", address(_token), tokenBal_, 0, 0 ); i++; } targets_[i] = "AAVE-V2-A"; calldata_[i] = abi.encodeWithSignature( "deposit(address,uint256,uint256,uint256)", address(stethContract), amt_, 0, 0 ); targets_[i + 1] = "AAVE-V2-A"; calldata_[i + 1] = abi.encodeWithSignature( "borrow(address,uint256,uint256,uint256,uint256)", address(wethContract), amt_, 2, 0, 0 ); targets_[i + 2] = "BASIC-A"; calldata_[i + 2] = abi.encodeWithSignature( "withdraw(address,uint256,address,uint256,uint256)", address(wethContract), transferAmt_, msg.sender, 0, 0 ); _vaultDsa.cast(targets_, calldata_, address(this)); (, , bool minIsOk_, , ) = validateFinalPosition(); require(minIsOk_, "excess-leverage"); emit leverageLog(amt_, transferAmt_); } /** * @dev If ratio is above then this function will allow anyone to payback WETH and withdraw astETH to msg.sender at 1:1 ratio. */ function deleverage(uint256 amt_) external nonReentrant { uint256 transferAmt_ = deleverageInternal(amt_); (, , , bool minGapIsOk_, ) = validateFinalPosition(); require(minGapIsOk_, "excess-deleverage"); emit deleverageLog(amt_, transferAmt_); } /** * @dev Function to allow users to max withdraw */ function deleverageAndWithdraw( uint256 deleverageAmt_, uint256 withdrawAmount_, address to_ ) external nonReentrant { uint256 transferAmt_ = deleverageInternal(deleverageAmt_); uint256 vtokenAmt_ = withdrawInternal(withdrawAmount_, to_, true); emit deleverageAndWithdrawLog( deleverageAmt_, transferAmt_, vtokenAmt_, to_ ); } }
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import "../common/helpers.sol"; contract Events is Helpers { event supplyLog( uint256 amount_, address indexed caller_, address indexed to_ ); event withdrawLog( uint256 amount_, address indexed caller_, address indexed to_ ); event leverageLog(uint256 amt_, uint256 transferAmt_); event deleverageLog(uint256 amt_, uint256 transferAmt_); event deleverageAndWithdrawLog( uint256 deleverageAmt_, uint256 transferAmt_, uint256 vtokenAmount_, address to_ ); }
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import "./variables.sol"; contract Helpers is Variables { /** * @dev reentrancy gaurd. */ modifier nonReentrant() { require(_status != 2, "ReentrancyGuard: reentrant call"); _status = 2; _; _status = 1; } /** * @dev Helper function to get current eth borrow rate on aave. */ function getWethBorrowRate() internal view returns (uint256 wethBorrowRate_) { (, , , , wethBorrowRate_, , , , , ) = aaveProtocolDataProvider .getReserveData(address(wethContract)); } /** * @dev Helper function to get current token collateral on aave. */ function getTokenCollateralAmount() internal view returns (uint256 tokenAmount_) { tokenAmount_ = _atoken.balanceOf(address(_vaultDsa)); } /** * @dev Helper function to get current steth collateral on aave. */ function getStethCollateralAmount() internal view returns (uint256 stEthAmount_) { stEthAmount_ = astethToken.balanceOf(address(_vaultDsa)); } /** * @dev Helper function to get current eth debt on aave. */ function getWethDebtAmount() internal view returns (uint256 wethDebtAmount_) { wethDebtAmount_ = awethVariableDebtToken.balanceOf(address(_vaultDsa)); } /** * @dev Helper function to token balances of everywhere. */ function getVaultBalances() public view returns ( uint256 tokenCollateralAmt_, uint256 stethCollateralAmt_, uint256 wethDebtAmt_, uint256 tokenVaultBal_, uint256 tokenDSABal_, uint256 netTokenBal_ ) { tokenCollateralAmt_ = getTokenCollateralAmount(); stethCollateralAmt_ = getStethCollateralAmount(); wethDebtAmt_ = getWethDebtAmount(); tokenVaultBal_ = _token.balanceOf(address(this)); tokenDSABal_ = _token.balanceOf(address(_vaultDsa)); netTokenBal_ = tokenCollateralAmt_ + tokenVaultBal_ + tokenDSABal_; } // returns net eth. net stETH + ETH - net ETH debt. function getNewProfits() public view returns (uint256 profits_) { uint256 stEthCol_ = getStethCollateralAmount(); uint256 stEthDsaBal_ = stethContract.balanceOf(address(_vaultDsa)); uint256 wethDsaBal_ = wethContract.balanceOf(address(_vaultDsa)); uint256 positiveEth_ = stEthCol_ + stEthDsaBal_ + wethDsaBal_; uint256 negativeEth_ = getWethDebtAmount() + _revenueEth; profits_ = negativeEth_ < positiveEth_ ? positiveEth_ - negativeEth_ : 0; } /** * @dev Helper function to get current exchange price and new revenue generated. */ function getCurrentExchangePrice() public view returns (uint256 exchangePrice_, uint256 newTokenRevenue_) { // net token balance is total balance. stETH collateral & ETH debt cancels out each other. (, , , , , uint256 netTokenBalance_) = getVaultBalances(); netTokenBalance_ -= _revenue; uint256 totalSupply_ = totalSupply(); uint256 exchangePriceWithRevenue_; if (totalSupply_ != 0) { exchangePriceWithRevenue_ = (netTokenBalance_ * 1e18) / totalSupply_; } else { exchangePriceWithRevenue_ = 1e18; } // Only calculate revenue if there's a profit if (exchangePriceWithRevenue_ > _lastRevenueExchangePrice) { uint256 newProfit_ = netTokenBalance_ - ((_lastRevenueExchangePrice * totalSupply_) / 1e18); newTokenRevenue_ = (newProfit_ * _revenueFee) / 10000; exchangePrice_ = ((netTokenBalance_ - newTokenRevenue_) * 1e18) / totalSupply_; } else { exchangePrice_ = exchangePriceWithRevenue_; } } struct ValidateFinalPosition { uint256 tokenPriceInBaseCurrency; uint256 ethPriceInBaseCurrency; uint256 excessDebtInBaseCurrency; uint256 netTokenColInBaseCurrency; uint256 netTokenSupplyInBaseCurrency; uint256 ratioMax; uint256 ratioMin; } /** * @dev Helper function to validate the safety of aave position after rebalancing. */ function validateFinalPosition() internal view returns ( bool criticalIsOk_, bool criticalGapIsOk_, bool minIsOk_, bool minGapIsOk_, bool withdrawIsOk_ ) { ( uint256 tokenColAmt_, uint256 stethColAmt_, uint256 wethDebt_, , , uint256 netTokenBal_ ) = getVaultBalances(); uint256 ethCoveringDebt_ = (stethColAmt_ * _ratios.stEthLimit) / 10000; uint256 excessDebt_ = ethCoveringDebt_ < wethDebt_ ? wethDebt_ - ethCoveringDebt_ : 0; if (excessDebt_ > 0) { IAavePriceOracle aaveOracle_ = IAavePriceOracle( aaveAddressProvider.getPriceOracle() ); ValidateFinalPosition memory validateFinalPosition_; validateFinalPosition_.tokenPriceInBaseCurrency = aaveOracle_ .getAssetPrice(address(_token)); validateFinalPosition_.ethPriceInBaseCurrency = aaveOracle_ .getAssetPrice(address(wethContract)); validateFinalPosition_.excessDebtInBaseCurrency = (excessDebt_ * validateFinalPosition_.ethPriceInBaseCurrency) / 1e18; validateFinalPosition_.netTokenColInBaseCurrency = (tokenColAmt_ * validateFinalPosition_.tokenPriceInBaseCurrency) / (10**_tokenDecimals); validateFinalPosition_.netTokenSupplyInBaseCurrency = (netTokenBal_ * validateFinalPosition_.tokenPriceInBaseCurrency) / (10**_tokenDecimals); validateFinalPosition_.ratioMax = (validateFinalPosition_.excessDebtInBaseCurrency * 10000) / validateFinalPosition_.netTokenColInBaseCurrency; validateFinalPosition_.ratioMin = (validateFinalPosition_.excessDebtInBaseCurrency * 10000) / validateFinalPosition_.netTokenSupplyInBaseCurrency; criticalIsOk_ = validateFinalPosition_.ratioMax < _ratios.maxLimit; criticalGapIsOk_ = validateFinalPosition_.ratioMax > _ratios.maxLimitGap; minIsOk_ = validateFinalPosition_.ratioMin < _ratios.minLimit; minGapIsOk_ = validateFinalPosition_.ratioMin > _ratios.minLimitGap; withdrawIsOk_ = validateFinalPosition_.ratioMax < (_ratios.maxLimit - 100); } else { criticalIsOk_ = true; minIsOk_ = true; } } /** * @dev Helper function to validate if the leverage amount is divided correctly amount other-vault-swaps and 1inch-swap . */ function validateLeverageAmt( address[] memory vaults_, uint256[] memory amts_, uint256 leverageAmt_, uint256 swapAmt_ ) internal pure returns (bool isOk_) { if (leverageAmt_ == 0 && swapAmt_ == 0) { isOk_ = true; return isOk_; } uint256 l_ = vaults_.length; isOk_ = l_ == amts_.length; if (isOk_) { uint256 totalAmt_ = swapAmt_; for (uint256 i = 0; i < l_; i++) { totalAmt_ = totalAmt_ + amts_[i]; } isOk_ = totalAmt_ <= leverageAmt_; // total amount should not be more than leverage amount isOk_ = isOk_ && ((leverageAmt_ * 9999) / 10000) < totalAmt_; // total amount should be more than (0.9999 * leverage amount). 0.01% slippage gap. } } }
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import "./interfaces.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; contract ConstantVariables is ERC20Upgradeable { IInstaIndex internal constant instaIndex = IInstaIndex(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723); IERC20 internal constant wethContract = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); IERC20 internal constant stethContract = IERC20(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84); IAaveProtocolDataProvider internal constant aaveProtocolDataProvider = IAaveProtocolDataProvider(0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d); IAaveAddressProvider internal constant aaveAddressProvider = IAaveAddressProvider(0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5); IERC20 internal constant awethVariableDebtToken = IERC20(0xF63B34710400CAd3e044cFfDcAb00a0f32E33eCf); IERC20 internal constant astethToken = IERC20(0x1982b2F5814301d4e9a8b0201555376e62F82428); IInstaList internal constant instaList = IInstaList(0x4c8a1BEb8a87765788946D6B19C6C6355194AbEb); } contract Variables is ConstantVariables { uint256 internal _status = 1; // only authorized addresses can rebalance mapping(address => bool) internal _isRebalancer; IERC20 internal _token; uint8 internal _tokenDecimals; uint256 internal _tokenMinLimit; IERC20 internal _atoken; IDSA internal _vaultDsa; struct Ratios { uint16 maxLimit; // Above this withdrawals are not allowed uint16 maxLimitGap; uint16 minLimit; // After leverage the ratio should be below minLimit & above minLimitGap uint16 minLimitGap; uint16 stEthLimit; // if 7500. Meaning stETH collateral covers 75% of the ETH debt. Excess ETH will be covered by token limit. // send borrow rate in 4 decimals from UI. In the smart contract it'll convert to 27 decimals which where is 100% uint128 maxBorrowRate; // maximum borrow rate above this leveraging should not happen } Ratios internal _ratios; // last revenue exchange price (helps in calculating revenue) // Exchange price when revenue got updated last. It'll only increase overtime. uint256 internal _lastRevenueExchangePrice; uint256 internal _revenueFee; // 1000 = 10% (10% of user's profit) uint256 internal _revenue; uint256 internal _revenueEth; uint256 internal _withdrawalFee; // 10000 = 100% uint256 internal _idealExcessAmt; // 10 means 0.1% of total stEth/Eth supply (collateral + ideal balance) uint256 internal _swapFee; // 5 means 0.05%. This is the fee on leverage function which allows swap of stETH -> ETH uint256 internal _saveSlippage; // 1e16 means 1% uint256 internal _deleverageFee; // 1 means 0.01% }
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IInstaIndex { function build( address owner_, uint256 accountVersion_, address origin_ ) external returns (address account_); } interface IDSA { function cast( string[] calldata _targetNames, bytes[] calldata _datas, address _origin ) external payable returns (bytes32); } interface IAaveProtocolDataProvider { function getReserveData(address asset) external view returns ( uint256 availableLiquidity, uint256 totalStableDebt, uint256 totalVariableDebt, uint256 liquidityRate, uint256 variableBorrowRate, uint256 stableBorrowRate, uint256 averageStableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex, uint40 lastUpdateTimestamp ); } interface IAaveAddressProvider { function getPriceOracle() external view returns (address); } interface IAavePriceOracle { function getAssetPrice(address _asset) external view returns (uint256); } interface TokenInterface { function approve(address, uint256) external; function transfer(address, uint256) external; function transferFrom( address, address, uint256 ) external; function deposit() external payable; function withdraw(uint256) external; function balanceOf(address) external view returns (uint256); function decimals() external view returns (uint256); function totalSupply() external view returns (uint256); } interface IInstaList { function accountID(address) external view returns (uint64); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20Upgradeable.sol"; import "./extensions/IERC20MetadataUpgradeable.sol"; import "../../utils/ContextUpgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC20_init_unchained(name_, symbol_); } function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, _allowances[owner][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = _allowances[owner][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; } _balances[to] += amount; emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Spend `amount` form the allowance of `owner` toward `spender`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[45] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); /** * @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 // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); /** * @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 // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20Upgradeable.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20MetadataUpgradeable is IERC20Upgradeable { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"deleverageAmt_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"transferAmt_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vtokenAmount_","type":"uint256"},{"indexed":false,"internalType":"address","name":"to_","type":"address"}],"name":"deleverageAndWithdrawLog","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amt_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"transferAmt_","type":"uint256"}],"name":"deleverageLog","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amt_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"transferAmt_","type":"uint256"}],"name":"leverageLog","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"},{"indexed":true,"internalType":"address","name":"caller_","type":"address"},{"indexed":true,"internalType":"address","name":"to_","type":"address"}],"name":"supplyLog","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"},{"indexed":true,"internalType":"address","name":"caller_","type":"address"},{"indexed":true,"internalType":"address","name":"to_","type":"address"}],"name":"withdrawLog","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amt_","type":"uint256"}],"name":"deleverage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"deleverageAmt_","type":"uint256"},{"internalType":"uint256","name":"withdrawAmount_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"}],"name":"deleverageAndWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCurrentExchangePrice","outputs":[{"internalType":"uint256","name":"exchangePrice_","type":"uint256"},{"internalType":"uint256","name":"newTokenRevenue_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNewProfits","outputs":[{"internalType":"uint256","name":"profits_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVaultBalances","outputs":[{"internalType":"uint256","name":"tokenCollateralAmt_","type":"uint256"},{"internalType":"uint256","name":"stethCollateralAmt_","type":"uint256"},{"internalType":"uint256","name":"wethDebtAmt_","type":"uint256"},{"internalType":"uint256","name":"tokenVaultBal_","type":"uint256"},{"internalType":"uint256","name":"tokenDSABal_","type":"uint256"},{"internalType":"uint256","name":"netTokenBal_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amt_","type":"uint256"}],"name":"leverage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"}],"name":"supply","outputs":[{"internalType":"uint256","name":"vtokenAmount_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"vtokenAmount_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080604052600160655534801561001557600080fd5b5061339b806100256000396000f3fe608060405234801561001057600080fd5b50600436106101205760003560e01c806370a08231116100ad578063a457c2d711610071578063a457c2d714610269578063a9059cbb1461027c578063acd431a81461028f578063cc4a0158146102a2578063dd62ed3e146102bf57600080fd5b806370a082311461020a5780638b2a4df514610233578063922a167c1461024657806395d89b411461024e5780639fdabec21461025657600080fd5b806322370685116100f4578063223706851461018b57806323b872dd146101c0578063313ce567146101d357806339509351146101e25780633b3fdb5c146101f557600080fd5b8062f714ce1461012557806306fdde031461014b578063095ea7b31461016057806318160ddd14610183575b600080fd5b610138610133366004612ed1565b6102f8565b6040519081526020015b60405180910390f35b610153610391565b60405161014291906130be565b61017361016e366004612e0f565b610423565b6040519015158152602001610142565b603554610138565b61019361043d565b604080519687526020870195909552938501929092526060840152608083015260a082015260c001610142565b6101736101ce366004612dce565b610580565b60405160128152602001610142565b6101736101f0366004612e0f565b6105a6565b610208610203366004612ef6565b6105e5565b005b610138610218366004612d5b565b6001600160a01b031660009081526033602052604090205490565b610138610241366004612e3b565b610687565b6101386107e9565b610153610974565b610208610264366004612eb8565b610983565b610173610277366004612e0f565b610a4c565b61017361028a366004612e0f565b610ae9565b61020861029d366004612eb8565b610af7565b6102aa6111eb565b60408051928352602083019190915201610142565b6101386102cd366004612d95565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6000606554600214156103265760405162461bcd60e51b815260040161031d906130d1565b60405180910390fd5b6002606555610337838360006112e3565b9050816001600160a01b0316336001600160a01b03167f8ff95236a9a9cdb79599917861aa3b49b5842ceb2ceae50fbdd2e8b67d8674e88560405161037e91815260200190565b60405180910390a3600160655592915050565b6060603680546103a0906132b5565b80601f01602080910402602001604051908101604052809291908181526020018280546103cc906132b5565b80156104195780601f106103ee57610100808354040283529160200191610419565b820191906000526020600020905b8154815290600101906020018083116103fc57829003601f168201915b5050505050905090565b6000336104318185856114bc565b60019150505b92915050565b60008060008060008061044e6115e0565b955061045861166a565b94506104626116b1565b6067546040516370a0823160e01b81523060048201529195506001600160a01b0316906370a082319060240160206040518083038186803b1580156104a657600080fd5b505afa1580156104ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104de9190612e9f565b606754606a546040516370a0823160e01b81526001600160a01b03918216600482015292955016906370a082319060240160206040518083038186803b15801561052757600080fd5b505afa15801561053b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055f9190612e9f565b91508161056c8488613108565b6105769190613108565b9050909192939495565b60003361058e8582856116f8565b61059985858561178a565b60019150505b9392505050565b3360008181526034602090815260408083206001600160a01b038716845290915281205490919061043190829086906105e0908790613108565b6114bc565b606554600214156106085760405162461bcd60e51b815260040161031d906130d1565b6002606555600061061884611958565b90506000610628848460016112e3565b60408051878152602081018590529081018290526001600160a01b03851660608201529091507fc3980c418b798a6662c222c72b5c2a1966dffb54a1314eaec235c8e27c7f0f679060800160405180910390a150506001606555505050565b6000606554600214156106ac5760405162461bcd60e51b815260040161031d906130d1565b60026065556067546001600160a01b038581169116146106fc5760405162461bcd60e51b815260206004820152600b60248201526a3bb937b733903a37b5b2b760a91b604482015260640161031d565b826107415760405162461bcd60e51b8152602060048201526015602482015274616d6f756e742063616e6e6f74206265207a65726f60581b604482015260640161031d565b60008061074c6111eb565b9150915061075a8282611e33565b606754610772906001600160a01b0316333088611e60565b8161078586670de0b6b3a7640000613230565b61078f9190613120565b925061079b8484611ecb565b6040518581526001600160a01b0385169033907fdfba3729393cce575d8987c05cfb77228e6a1d84474cd0cd911980eb937a03289060200160405180910390a3505060016065559392505050565b6000806107f461166a565b606a546040516370a0823160e01b81526001600160a01b03909116600482015290915060009073ae7ab96520de3a18e5e111b5eaab095312d7fe84906370a082319060240160206040518083038186803b15801561085157600080fd5b505afa158015610865573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108899190612e9f565b606a546040516370a0823160e01b81526001600160a01b03909116600482015290915060009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a082319060240160206040518083038186803b1580156108e657600080fd5b505afa1580156108fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091e9190612e9f565b905060008161092d8486613108565b6109379190613108565b90506000606f546109466116b1565b6109509190613108565b905081811061096057600061096a565b61096a8183613272565b9550505050505090565b6060603780546103a0906132b5565b606554600214156109a65760405162461bcd60e51b815260040161031d906130d1565b600260655560006109b682611958565b905060006109c2611faa565b50935050505080610a095760405162461bcd60e51b81526020600482015260116024820152706578636573732d64656c6576657261676560781b604482015260640161031d565b60408051848152602081018490527f0f625c5d1a824573014fa3e56ac0e2a26b2689cf61d59b9e8740f3c2059c408c910160405180910390a15050600160655550565b3360008181526034602090815260408083206001600160a01b038716845290915281205490919083811015610ad15760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161031d565b610ade82868684036114bc565b506001949350505050565b60003361043181858561178a565b60655460021415610b1a5760405162461bcd60e51b815260040161031d906130d1565b600260655580610b5f5760405162461bcd60e51b815260206004820152601060248201526f1b9bdd0b5d985b1a590b585b5bdd5b9d60821b604482015260640161031d565b606a54610b8d9073ae7ab96520de3a18e5e111b5eaab095312d7fe849033906001600160a01b031684611e60565b600061271060725483610ba09190613230565b610baa9190613120565b90506000610bb88284613272565b905081606f6000828254610bcc9190613108565b90915550506067546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015610c1557600080fd5b505afa158015610c29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4d9190612e9f565b9050606854811115610c7657606a54606754610c76916001600160a01b0391821691168361239a565b606754606a546040516370a0823160e01b81526001600160a01b0391821660048201529116906370a082319060240160206040518083038186803b158015610cbd57600080fd5b505afa158015610cd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf59190612e9f565b90506000806068548311610d0a576003610d0d565b60045b60ff16905060008167ffffffffffffffff811115610d2d57610d2d613337565b604051908082528060200260200182016040528015610d6057816020015b6060815260200190600190039081610d4b5790505b50905060008267ffffffffffffffff811115610d7e57610d7e613337565b604051908082528060200260200182016040528015610db157816020015b6060815260200190600190039081610d9c5790505b509050606854851115610e785760405180604001604052806009815260200168414156452d56322d4160b81b815250828581518110610df257610df2613321565b6020908102919091010152606754604051610e20916001600160a01b03169087906000908190602401612fcc565b60408051601f198184030181529190526020810180516001600160e01b031663ce88b43960e01b1790528151829086908110610e5e57610e5e613321565b60200260200101819052508380610e74906132f0565b9450505b60405180604001604052806009815260200168414156452d56322d4160b81b815250828581518110610eac57610eac613321565b602002602001018190525073ae7ab96520de3a18e5e111b5eaab095312d7fe8488600080604051602401610ee39493929190612fcc565b60408051601f198184030181529190526020810180516001600160e01b031663ce88b43960e01b1790528151829086908110610f2157610f21613321565b602002602001018190525060405180604001604052806009815260200168414156452d56322d4160b81b81525082856001610f5c9190613108565b81518110610f6c57610f6c613321565b602090810291909101015260405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26024820152604481018990526002606482015260006084820181905260a482015260c40160408051601f198184030181529190526020810180516001600160e01b031663355e69ef60e11b17905281610fe9866001613108565b81518110610ff957610ff9613321565b60200260200101819052506040518060400160405280600781526020016642415349432d4160c81b815250828560026110329190613108565b8151811061104257611042613321565b602002602001018190525073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2863360008060405160240161107b959493929190612f96565b60408051601f198184030181529190526020810180516001600160e01b03166325e9d5c160e11b179052816110b1866002613108565b815181106110c1576110c1613321565b6020908102919091010152606a546040516324c1324d60e21b81526001600160a01b0390911690639304c9349061110090859085903090600401612ff8565b602060405180830381600087803b15801561111a57600080fd5b505af115801561112e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111529190612e9f565b50600061115d611faa565b505092505050806111a25760405162461bcd60e51b815260206004820152600f60248201526e6578636573732d6c6576657261676560881b604482015260640161031d565b604080518a8152602081018990527fbd2b28f4c78ecfe1830784bce25af4451c2200f38cf524e646d2f5616493a0ff910160405180910390a15050600160655550505050505050565b60008060006111f861043d565b95505050505050606e548161120d9190613272565b9050600061121a60355490565b905060008115611248578161123784670de0b6b3a7640000613230565b6112419190613120565b9050611253565b50670de0b6b3a76400005b606c548111156112d8576000670de0b6b3a764000083606c546112769190613230565b6112809190613120565b61128a9085613272565b9050612710606d548261129d9190613230565b6112a79190613120565b9450826112b48686613272565b6112c690670de0b6b3a7640000613230565b6112d09190613120565b9550506112dc565b8094505b5050509091565b60008361132a5760405162461bcd60e51b8152602060048201526015602482015274616d6f756e742063616e6e6f74206265207a65726f60581b604482015260640161031d565b6000806113356111eb565b915091506113438282611e33565b60001986141561138357336000908152603360205260409020549250670de0b6b3a76400006113728385613230565b61137c9190613120565b95506113a3565b8161139687670de0b6b3a7640000613230565b6113a09190613120565b92505b6113ad33846123cf565b6000612710607054886113c09190613230565b6113ca9190613120565b905060006113d88289613272565b905060006113e58261251d565b90506113f1828261269a565b60006113fb611faa565b9450505050508061143f5760405162461bcd60e51b815260206004820152600e60248201526d706f736974696f6e2d7269736b7960901b604482015260640161031d565b606754611456906001600160a01b03168a8561239a565b87156114af576000611466611faa565b509350505050806114ad5760405162461bcd60e51b81526020600482015260116024820152706578636573732d64656c6576657261676560781b604482015260640161031d565b505b5050505050509392505050565b6001600160a01b03831661151e5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161031d565b6001600160a01b03821661157f5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161031d565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b606954606a546040516370a0823160e01b81526001600160a01b03918216600482015260009291909116906370a08231906024015b60206040518083038186803b15801561162d57600080fd5b505afa158015611641573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116659190612e9f565b905090565b606a546040516370a0823160e01b81526001600160a01b039091166004820152600090731982b2f5814301d4e9a8b0201555376e62f82428906370a0823190602401611615565b606a546040516370a0823160e01b81526001600160a01b03909116600482015260009073f63b34710400cad3e044cffdcab00a0f32e33ecf906370a0823190602401611615565b6001600160a01b03838116600090815260346020908152604080832093861683529290522054600019811461178457818110156117775760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161031d565b61178484848484036114bc565b50505050565b6001600160a01b0383166117ee5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161031d565b6001600160a01b0382166118505760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161031d565b6001600160a01b038316600090815260336020526040902054818110156118c85760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161031d565b6001600160a01b038085166000908152603360205260408082208585039055918516815290812080548492906118ff908490613108565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161194b91815260200190565b60405180910390a3611784565b600080821161199c5760405162461bcd60e51b815260206004820152601060248201526f1b9bdd0b5d985b1a590b585b5bdd5b9d60821b604482015260640161031d565b606a546119ca9073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29033906001600160a01b031685611e60565b604051636cfaf5e960e01b81523360048201526000908190734c8a1beb8a87765788946d6b19c6c6355194abeb90636cfaf5e99060240160206040518083038186803b158015611a1957600080fd5b505afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190612f24565b67ffffffffffffffff1611905060008082611a6d576003611a70565b60025b60ff16905060008167ffffffffffffffff811115611a9057611a90613337565b604051908082528060200260200182016040528015611ac357816020015b6060815260200190600190039081611aae5790505b50905060008267ffffffffffffffff811115611ae157611ae1613337565b604051908082528060200260200182016040528015611b1457816020015b6060815260200190600190039081611aff5790505b50905060405180604001604052806009815260200168414156452d56322d4160b81b81525082600081518110611b4c57611b4c613321565b602090810291909101015260405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26024820152604481018890526002606482015260006084820181905260a482015260c40160408051601f198184030181529190526020810180516001600160e01b0316634e5e60e760e01b17905281518290600090611bd057611bd0613321565b602002602001018190525084611cc65761271060745488611bf19190613230565b611bfb9190613120565b611c059088613108565b955060405180604001604052806009815260200168414156452d56322d4160b81b81525082600181518110611c3c57611c3c613321565b602002602001018190525073ae7ab96520de3a18e5e111b5eaab095312d7fe8486600080604051602401611c739493929190612fcc565b60408051601f198184030181529190526020810180516001600160e01b03166322996bbb60e11b179052815182906001908110611cb257611cb2613321565b602002602001018190525060029350611cce565b869550600193505b6040518060400160405280600781526020016642415349432d4160c81b815250828581518110611d0057611d00613321565b602002602001018190525084611d2a5773ae7ab96520de3a18e5e111b5eaab095312d7fe84611d40565b731982b2f5814301d4e9a8b0201555376e62f824285b8633600080604051602401611d59959493929190612f96565b60408051601f198184030181529190526020810180516001600160e01b03166325e9d5c160e11b1790528151829086908110611d9757611d97613321565b6020908102919091010152606a546040516324c1324d60e21b81526001600160a01b0390911690639304c93490611dd690859085903090600401612ff8565b602060405180830381600087803b158015611df057600080fd5b505af1158015611e04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e289190612e9f565b505050505050919050565b606c54821115611e5c5781606c8190555080606e6000828254611e569190613108565b90915550505b5050565b6040516001600160a01b03808516602483015283166044820152606481018290526117849085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612adb565b6001600160a01b038216611f215760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161031d565b8060356000828254611f339190613108565b90915550506001600160a01b03821660009081526033602052604081208054839290611f60908490613108565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6000806000806000806000806000611fc061043d565b606b549599509397509195509193506000926127109250611ff2915068010000000000000000900461ffff1686613230565b611ffc9190613120565b9050600083821061200e576000612018565b6120188285613272565b9050801561238457600073b53c1a33016b2dc2ff3653530bff1848a515c8c56001600160a01b031663fca513a86040518163ffffffff1660e01b815260040160206040518083038186803b15801561206f57600080fd5b505afa158015612083573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a79190612d78565b90506120e96040518060e00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60675460405163b3596f0760e01b81526001600160a01b0391821660048201529083169063b3596f079060240160206040518083038186803b15801561212e57600080fd5b505afa158015612142573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121669190612e9f565b815260405163b3596f0760e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260048201526001600160a01b0383169063b3596f079060240160206040518083038186803b1580156121bb57600080fd5b505afa1580156121cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f39190612e9f565b60208201819052670de0b6b3a76400009061220e9085613230565b6122189190613120565b604082015260675461223590600160a01b900460ff16600a613185565b8151612241908a613230565b61224b9190613120565b606082015260675461226890600160a01b900460ff16600a613185565b81516122749087613230565b61227e9190613120565b60808201526060810151604082015161229990612710613230565b6122a39190613120565b60a0820152608081015160408201516122be90612710613230565b6122c89190613120565b8160c0018181525050606b60000160009054906101000a900461ffff1661ffff168160a00151109c50606b60000160029054906101000a900461ffff1661ffff168160a00151119b50606b60000160049054906101000a900461ffff1661ffff168160c00151109a50606b60000160069054906101000a900461ffff1661ffff168160c001511199506064606b60000160009054906101000a900461ffff16612371919061324f565b61ffff168160a00151109850505061238d565b60019a50600198505b5050505050509091929394565b6040516001600160a01b0383166024820152604481018290526123ca90849063a9059cbb60e01b90606401611e94565b505050565b6001600160a01b03821661242f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161031d565b6001600160a01b038216600090815260336020526040902054818110156124a35760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161031d565b6001600160a01b03831660009081526033602052604081208383039055603580548492906124d2908490613272565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6060600082116125605760405162461bcd60e51b815260206004820152600e60248201526d185b5bdd5b9d0b5a5b9d985b1a5960921b604482015260640161031d565b60008060008061256e61043d565b95509550955050509350808611156125bc5760405162461bcd60e51b8152602060048201526011602482015270195e18d95cdccb5dda5d1a191c985dd85b607a1b604482015260640161031d565b604080516003808252608082019092529060208201606080368337019050509450600a831115612611576125f08684612bad565b8660008151811061260357612603613321565b602090810291909101015295505b600a821180156126215750600086115b15612651576126308683612bad565b8660018151811061264357612643613321565b602090810291909101015295505b600a841180156126615750600086115b15612691576126708685612bad565b8660028151811061268357612683613321565b602090810291909101015295505b50505050919050565b81816000815181106126ae576126ae613321565b602002602001015114156126c0575050565b6000816002815181106126d5576126d5613321565b6020026020010151826001815181106126f0576126f0613321565b60200260200101518360008151811061270b5761270b613321565b602002602001015161271d9190613108565b6127279190613108565b905080831461276e5760405162461bcd60e51b81526020600482015260136024820152721d1c985b9cd9995c9ccb5b9bdd0b5d985b1a59606a1b604482015260640161031d565b60008060008460028151811061278657612786613321565b6020026020010151856001815181106127a1576127a1613321565b60200260200101516127b39190613108565b90506000856002815181106127ca576127ca613321565b602002602001015111156127e657816127e2816132f0565b9250505b80156127fa57816127f6816132f0565b9250505b60008267ffffffffffffffff81111561281557612815613337565b60405190808252806020026020018201604052801561284857816020015b60608152602001906001900390816128335790505b50905060008367ffffffffffffffff81111561286657612866613337565b60405190808252806020026020018201604052801561289957816020015b60608152602001906001900390816128845790505b5090506000876002815181106128b1576128b1613321565b602002602001015111156129985760405180604001604052806009815260200168414156452d56322d4160b81b8152508286815181106128f3576128f3613321565b602090810291909101015260675487516001600160a01b03909116908890600290811061292257612922613321565b60200260200101516000806040516024016129409493929190612fcc565b60408051601f198184030181529190526020810180516001600160e01b03166322996bbb60e11b179052815182908790811061297e5761297e613321565b60200260200101819052508480612994906132f0565b9550505b8215612a4a576040518060400160405280600781526020016642415349432d4160c81b8152508286815181106129d0576129d0613321565b6020908102919091010152606754604051612a00916001600160a01b031690859030906000908190602401612f96565b60408051601f198184030181529190526020810180516001600160e01b03166325e9d5c160e11b1790528151829087908110612a3e57612a3e613321565b60200260200101819052505b606a546040516324c1324d60e21b81526001600160a01b0390911690639304c93490612a7e90859085903090600401612ff8565b602060405180830381600087803b158015612a9857600080fd5b505af1158015612aac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad09190612e9f565b505050505050505050565b6000612b30826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612bda9092919063ffffffff16565b8051909150156123ca5780806020019051810190612b4e9190612e7d565b6123ca5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161031d565b600080600084841115612bc35750600093612bd2565b5082612bcf8186613272565b94505b939492505050565b6060612be98484600085612bf1565b949350505050565b606082471015612c525760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161031d565b6001600160a01b0385163b612ca95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161031d565b600080866001600160a01b03168587604051612cc59190612f7a565b60006040518083038185875af1925050503d8060008114612d02576040519150601f19603f3d011682016040523d82523d6000602084013e612d07565b606091505b5091509150612d17828286612d22565b979650505050505050565b60608315612d3157508161059f565b825115612d415782518084602001fd5b8160405162461bcd60e51b815260040161031d91906130be565b600060208284031215612d6d57600080fd5b813561059f8161334d565b600060208284031215612d8a57600080fd5b815161059f8161334d565b60008060408385031215612da857600080fd5b8235612db38161334d565b91506020830135612dc38161334d565b809150509250929050565b600080600060608486031215612de357600080fd5b8335612dee8161334d565b92506020840135612dfe8161334d565b929592945050506040919091013590565b60008060408385031215612e2257600080fd5b8235612e2d8161334d565b946020939093013593505050565b600080600060608486031215612e5057600080fd5b8335612e5b8161334d565b9250602084013591506040840135612e728161334d565b809150509250925092565b600060208284031215612e8f57600080fd5b8151801515811461059f57600080fd5b600060208284031215612eb157600080fd5b5051919050565b600060208284031215612eca57600080fd5b5035919050565b60008060408385031215612ee457600080fd5b823591506020830135612dc38161334d565b600080600060608486031215612f0b57600080fd5b83359250602084013591506040840135612e728161334d565b600060208284031215612f3657600080fd5b815167ffffffffffffffff8116811461059f57600080fd5b60008151808452612f66816020860160208601613289565b601f01601f19169290920160200192915050565b60008251612f8c818460208701613289565b9190910192915050565b6001600160a01b039586168152602081019490945291909316604083015260ff9283166060830152909116608082015260a00190565b6001600160a01b03949094168452602084019290925260ff908116604084015216606082015260800190565b6000606082016060835280865180835260808501915060808160051b8601019250602080890160005b8381101561304f57607f1988870301855261303d868351612f4e565b95509382019390820190600101613021565b505085840381870152875180855281850193509150600582901b8401810188820160005b848110156130a157601f1987840301865261308f838351612f4e565b95840195925090830190600101613073565b50506001600160a01b03881660408801529450612be99350505050565b60208152600061059f6020830184612f4e565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6000821982111561311b5761311b61330b565b500190565b60008261313d57634e487b7160e01b600052601260045260246000fd5b500490565b600181815b8085111561317d5781600019048211156131635761316361330b565b8085161561317057918102915b93841c9390800290613147565b509250929050565b600061059f60ff84168360008261319e57506001610437565b816131ab57506000610437565b81600181146131c157600281146131cb576131e7565b6001915050610437565b60ff8411156131dc576131dc61330b565b50506001821b610437565b5060208310610133831016604e8410600b841016171561320a575081810a610437565b6132148383613142565b80600019048211156132285761322861330b565b029392505050565b600081600019048311821515161561324a5761324a61330b565b500290565b600061ffff8381169083168181101561326a5761326a61330b565b039392505050565b6000828210156132845761328461330b565b500390565b60005b838110156132a457818101518382015260200161328c565b838111156117845750506000910152565b600181811c908216806132c957607f821691505b602082108114156132ea57634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156133045761330461330b565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461336257600080fd5b5056fea2646970667358221220393338cf4fa7412273740334cbc4dd411d569395435b47e3dc9f027d51e33e0f64736f6c63430008060033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101205760003560e01c806370a08231116100ad578063a457c2d711610071578063a457c2d714610269578063a9059cbb1461027c578063acd431a81461028f578063cc4a0158146102a2578063dd62ed3e146102bf57600080fd5b806370a082311461020a5780638b2a4df514610233578063922a167c1461024657806395d89b411461024e5780639fdabec21461025657600080fd5b806322370685116100f4578063223706851461018b57806323b872dd146101c0578063313ce567146101d357806339509351146101e25780633b3fdb5c146101f557600080fd5b8062f714ce1461012557806306fdde031461014b578063095ea7b31461016057806318160ddd14610183575b600080fd5b610138610133366004612ed1565b6102f8565b6040519081526020015b60405180910390f35b610153610391565b60405161014291906130be565b61017361016e366004612e0f565b610423565b6040519015158152602001610142565b603554610138565b61019361043d565b604080519687526020870195909552938501929092526060840152608083015260a082015260c001610142565b6101736101ce366004612dce565b610580565b60405160128152602001610142565b6101736101f0366004612e0f565b6105a6565b610208610203366004612ef6565b6105e5565b005b610138610218366004612d5b565b6001600160a01b031660009081526033602052604090205490565b610138610241366004612e3b565b610687565b6101386107e9565b610153610974565b610208610264366004612eb8565b610983565b610173610277366004612e0f565b610a4c565b61017361028a366004612e0f565b610ae9565b61020861029d366004612eb8565b610af7565b6102aa6111eb565b60408051928352602083019190915201610142565b6101386102cd366004612d95565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6000606554600214156103265760405162461bcd60e51b815260040161031d906130d1565b60405180910390fd5b6002606555610337838360006112e3565b9050816001600160a01b0316336001600160a01b03167f8ff95236a9a9cdb79599917861aa3b49b5842ceb2ceae50fbdd2e8b67d8674e88560405161037e91815260200190565b60405180910390a3600160655592915050565b6060603680546103a0906132b5565b80601f01602080910402602001604051908101604052809291908181526020018280546103cc906132b5565b80156104195780601f106103ee57610100808354040283529160200191610419565b820191906000526020600020905b8154815290600101906020018083116103fc57829003601f168201915b5050505050905090565b6000336104318185856114bc565b60019150505b92915050565b60008060008060008061044e6115e0565b955061045861166a565b94506104626116b1565b6067546040516370a0823160e01b81523060048201529195506001600160a01b0316906370a082319060240160206040518083038186803b1580156104a657600080fd5b505afa1580156104ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104de9190612e9f565b606754606a546040516370a0823160e01b81526001600160a01b03918216600482015292955016906370a082319060240160206040518083038186803b15801561052757600080fd5b505afa15801561053b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055f9190612e9f565b91508161056c8488613108565b6105769190613108565b9050909192939495565b60003361058e8582856116f8565b61059985858561178a565b60019150505b9392505050565b3360008181526034602090815260408083206001600160a01b038716845290915281205490919061043190829086906105e0908790613108565b6114bc565b606554600214156106085760405162461bcd60e51b815260040161031d906130d1565b6002606555600061061884611958565b90506000610628848460016112e3565b60408051878152602081018590529081018290526001600160a01b03851660608201529091507fc3980c418b798a6662c222c72b5c2a1966dffb54a1314eaec235c8e27c7f0f679060800160405180910390a150506001606555505050565b6000606554600214156106ac5760405162461bcd60e51b815260040161031d906130d1565b60026065556067546001600160a01b038581169116146106fc5760405162461bcd60e51b815260206004820152600b60248201526a3bb937b733903a37b5b2b760a91b604482015260640161031d565b826107415760405162461bcd60e51b8152602060048201526015602482015274616d6f756e742063616e6e6f74206265207a65726f60581b604482015260640161031d565b60008061074c6111eb565b9150915061075a8282611e33565b606754610772906001600160a01b0316333088611e60565b8161078586670de0b6b3a7640000613230565b61078f9190613120565b925061079b8484611ecb565b6040518581526001600160a01b0385169033907fdfba3729393cce575d8987c05cfb77228e6a1d84474cd0cd911980eb937a03289060200160405180910390a3505060016065559392505050565b6000806107f461166a565b606a546040516370a0823160e01b81526001600160a01b03909116600482015290915060009073ae7ab96520de3a18e5e111b5eaab095312d7fe84906370a082319060240160206040518083038186803b15801561085157600080fd5b505afa158015610865573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108899190612e9f565b606a546040516370a0823160e01b81526001600160a01b03909116600482015290915060009073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2906370a082319060240160206040518083038186803b1580156108e657600080fd5b505afa1580156108fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091e9190612e9f565b905060008161092d8486613108565b6109379190613108565b90506000606f546109466116b1565b6109509190613108565b905081811061096057600061096a565b61096a8183613272565b9550505050505090565b6060603780546103a0906132b5565b606554600214156109a65760405162461bcd60e51b815260040161031d906130d1565b600260655560006109b682611958565b905060006109c2611faa565b50935050505080610a095760405162461bcd60e51b81526020600482015260116024820152706578636573732d64656c6576657261676560781b604482015260640161031d565b60408051848152602081018490527f0f625c5d1a824573014fa3e56ac0e2a26b2689cf61d59b9e8740f3c2059c408c910160405180910390a15050600160655550565b3360008181526034602090815260408083206001600160a01b038716845290915281205490919083811015610ad15760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161031d565b610ade82868684036114bc565b506001949350505050565b60003361043181858561178a565b60655460021415610b1a5760405162461bcd60e51b815260040161031d906130d1565b600260655580610b5f5760405162461bcd60e51b815260206004820152601060248201526f1b9bdd0b5d985b1a590b585b5bdd5b9d60821b604482015260640161031d565b606a54610b8d9073ae7ab96520de3a18e5e111b5eaab095312d7fe849033906001600160a01b031684611e60565b600061271060725483610ba09190613230565b610baa9190613120565b90506000610bb88284613272565b905081606f6000828254610bcc9190613108565b90915550506067546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015610c1557600080fd5b505afa158015610c29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4d9190612e9f565b9050606854811115610c7657606a54606754610c76916001600160a01b0391821691168361239a565b606754606a546040516370a0823160e01b81526001600160a01b0391821660048201529116906370a082319060240160206040518083038186803b158015610cbd57600080fd5b505afa158015610cd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf59190612e9f565b90506000806068548311610d0a576003610d0d565b60045b60ff16905060008167ffffffffffffffff811115610d2d57610d2d613337565b604051908082528060200260200182016040528015610d6057816020015b6060815260200190600190039081610d4b5790505b50905060008267ffffffffffffffff811115610d7e57610d7e613337565b604051908082528060200260200182016040528015610db157816020015b6060815260200190600190039081610d9c5790505b509050606854851115610e785760405180604001604052806009815260200168414156452d56322d4160b81b815250828581518110610df257610df2613321565b6020908102919091010152606754604051610e20916001600160a01b03169087906000908190602401612fcc565b60408051601f198184030181529190526020810180516001600160e01b031663ce88b43960e01b1790528151829086908110610e5e57610e5e613321565b60200260200101819052508380610e74906132f0565b9450505b60405180604001604052806009815260200168414156452d56322d4160b81b815250828581518110610eac57610eac613321565b602002602001018190525073ae7ab96520de3a18e5e111b5eaab095312d7fe8488600080604051602401610ee39493929190612fcc565b60408051601f198184030181529190526020810180516001600160e01b031663ce88b43960e01b1790528151829086908110610f2157610f21613321565b602002602001018190525060405180604001604052806009815260200168414156452d56322d4160b81b81525082856001610f5c9190613108565b81518110610f6c57610f6c613321565b602090810291909101015260405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26024820152604481018990526002606482015260006084820181905260a482015260c40160408051601f198184030181529190526020810180516001600160e01b031663355e69ef60e11b17905281610fe9866001613108565b81518110610ff957610ff9613321565b60200260200101819052506040518060400160405280600781526020016642415349432d4160c81b815250828560026110329190613108565b8151811061104257611042613321565b602002602001018190525073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2863360008060405160240161107b959493929190612f96565b60408051601f198184030181529190526020810180516001600160e01b03166325e9d5c160e11b179052816110b1866002613108565b815181106110c1576110c1613321565b6020908102919091010152606a546040516324c1324d60e21b81526001600160a01b0390911690639304c9349061110090859085903090600401612ff8565b602060405180830381600087803b15801561111a57600080fd5b505af115801561112e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111529190612e9f565b50600061115d611faa565b505092505050806111a25760405162461bcd60e51b815260206004820152600f60248201526e6578636573732d6c6576657261676560881b604482015260640161031d565b604080518a8152602081018990527fbd2b28f4c78ecfe1830784bce25af4451c2200f38cf524e646d2f5616493a0ff910160405180910390a15050600160655550505050505050565b60008060006111f861043d565b95505050505050606e548161120d9190613272565b9050600061121a60355490565b905060008115611248578161123784670de0b6b3a7640000613230565b6112419190613120565b9050611253565b50670de0b6b3a76400005b606c548111156112d8576000670de0b6b3a764000083606c546112769190613230565b6112809190613120565b61128a9085613272565b9050612710606d548261129d9190613230565b6112a79190613120565b9450826112b48686613272565b6112c690670de0b6b3a7640000613230565b6112d09190613120565b9550506112dc565b8094505b5050509091565b60008361132a5760405162461bcd60e51b8152602060048201526015602482015274616d6f756e742063616e6e6f74206265207a65726f60581b604482015260640161031d565b6000806113356111eb565b915091506113438282611e33565b60001986141561138357336000908152603360205260409020549250670de0b6b3a76400006113728385613230565b61137c9190613120565b95506113a3565b8161139687670de0b6b3a7640000613230565b6113a09190613120565b92505b6113ad33846123cf565b6000612710607054886113c09190613230565b6113ca9190613120565b905060006113d88289613272565b905060006113e58261251d565b90506113f1828261269a565b60006113fb611faa565b9450505050508061143f5760405162461bcd60e51b815260206004820152600e60248201526d706f736974696f6e2d7269736b7960901b604482015260640161031d565b606754611456906001600160a01b03168a8561239a565b87156114af576000611466611faa565b509350505050806114ad5760405162461bcd60e51b81526020600482015260116024820152706578636573732d64656c6576657261676560781b604482015260640161031d565b505b5050505050509392505050565b6001600160a01b03831661151e5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161031d565b6001600160a01b03821661157f5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161031d565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b606954606a546040516370a0823160e01b81526001600160a01b03918216600482015260009291909116906370a08231906024015b60206040518083038186803b15801561162d57600080fd5b505afa158015611641573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116659190612e9f565b905090565b606a546040516370a0823160e01b81526001600160a01b039091166004820152600090731982b2f5814301d4e9a8b0201555376e62f82428906370a0823190602401611615565b606a546040516370a0823160e01b81526001600160a01b03909116600482015260009073f63b34710400cad3e044cffdcab00a0f32e33ecf906370a0823190602401611615565b6001600160a01b03838116600090815260346020908152604080832093861683529290522054600019811461178457818110156117775760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161031d565b61178484848484036114bc565b50505050565b6001600160a01b0383166117ee5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161031d565b6001600160a01b0382166118505760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161031d565b6001600160a01b038316600090815260336020526040902054818110156118c85760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161031d565b6001600160a01b038085166000908152603360205260408082208585039055918516815290812080548492906118ff908490613108565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161194b91815260200190565b60405180910390a3611784565b600080821161199c5760405162461bcd60e51b815260206004820152601060248201526f1b9bdd0b5d985b1a590b585b5bdd5b9d60821b604482015260640161031d565b606a546119ca9073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29033906001600160a01b031685611e60565b604051636cfaf5e960e01b81523360048201526000908190734c8a1beb8a87765788946d6b19c6c6355194abeb90636cfaf5e99060240160206040518083038186803b158015611a1957600080fd5b505afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190612f24565b67ffffffffffffffff1611905060008082611a6d576003611a70565b60025b60ff16905060008167ffffffffffffffff811115611a9057611a90613337565b604051908082528060200260200182016040528015611ac357816020015b6060815260200190600190039081611aae5790505b50905060008267ffffffffffffffff811115611ae157611ae1613337565b604051908082528060200260200182016040528015611b1457816020015b6060815260200190600190039081611aff5790505b50905060405180604001604052806009815260200168414156452d56322d4160b81b81525082600081518110611b4c57611b4c613321565b602090810291909101015260405173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26024820152604481018890526002606482015260006084820181905260a482015260c40160408051601f198184030181529190526020810180516001600160e01b0316634e5e60e760e01b17905281518290600090611bd057611bd0613321565b602002602001018190525084611cc65761271060745488611bf19190613230565b611bfb9190613120565b611c059088613108565b955060405180604001604052806009815260200168414156452d56322d4160b81b81525082600181518110611c3c57611c3c613321565b602002602001018190525073ae7ab96520de3a18e5e111b5eaab095312d7fe8486600080604051602401611c739493929190612fcc565b60408051601f198184030181529190526020810180516001600160e01b03166322996bbb60e11b179052815182906001908110611cb257611cb2613321565b602002602001018190525060029350611cce565b869550600193505b6040518060400160405280600781526020016642415349432d4160c81b815250828581518110611d0057611d00613321565b602002602001018190525084611d2a5773ae7ab96520de3a18e5e111b5eaab095312d7fe84611d40565b731982b2f5814301d4e9a8b0201555376e62f824285b8633600080604051602401611d59959493929190612f96565b60408051601f198184030181529190526020810180516001600160e01b03166325e9d5c160e11b1790528151829086908110611d9757611d97613321565b6020908102919091010152606a546040516324c1324d60e21b81526001600160a01b0390911690639304c93490611dd690859085903090600401612ff8565b602060405180830381600087803b158015611df057600080fd5b505af1158015611e04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e289190612e9f565b505050505050919050565b606c54821115611e5c5781606c8190555080606e6000828254611e569190613108565b90915550505b5050565b6040516001600160a01b03808516602483015283166044820152606481018290526117849085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612adb565b6001600160a01b038216611f215760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161031d565b8060356000828254611f339190613108565b90915550506001600160a01b03821660009081526033602052604081208054839290611f60908490613108565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6000806000806000806000806000611fc061043d565b606b549599509397509195509193506000926127109250611ff2915068010000000000000000900461ffff1686613230565b611ffc9190613120565b9050600083821061200e576000612018565b6120188285613272565b9050801561238457600073b53c1a33016b2dc2ff3653530bff1848a515c8c56001600160a01b031663fca513a86040518163ffffffff1660e01b815260040160206040518083038186803b15801561206f57600080fd5b505afa158015612083573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a79190612d78565b90506120e96040518060e00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60675460405163b3596f0760e01b81526001600160a01b0391821660048201529083169063b3596f079060240160206040518083038186803b15801561212e57600080fd5b505afa158015612142573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121669190612e9f565b815260405163b3596f0760e01b815273c02aaa39b223fe8d0a0e5c4f27ead9083c756cc260048201526001600160a01b0383169063b3596f079060240160206040518083038186803b1580156121bb57600080fd5b505afa1580156121cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f39190612e9f565b60208201819052670de0b6b3a76400009061220e9085613230565b6122189190613120565b604082015260675461223590600160a01b900460ff16600a613185565b8151612241908a613230565b61224b9190613120565b606082015260675461226890600160a01b900460ff16600a613185565b81516122749087613230565b61227e9190613120565b60808201526060810151604082015161229990612710613230565b6122a39190613120565b60a0820152608081015160408201516122be90612710613230565b6122c89190613120565b8160c0018181525050606b60000160009054906101000a900461ffff1661ffff168160a00151109c50606b60000160029054906101000a900461ffff1661ffff168160a00151119b50606b60000160049054906101000a900461ffff1661ffff168160c00151109a50606b60000160069054906101000a900461ffff1661ffff168160c001511199506064606b60000160009054906101000a900461ffff16612371919061324f565b61ffff168160a00151109850505061238d565b60019a50600198505b5050505050509091929394565b6040516001600160a01b0383166024820152604481018290526123ca90849063a9059cbb60e01b90606401611e94565b505050565b6001600160a01b03821661242f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161031d565b6001600160a01b038216600090815260336020526040902054818110156124a35760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161031d565b6001600160a01b03831660009081526033602052604081208383039055603580548492906124d2908490613272565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6060600082116125605760405162461bcd60e51b815260206004820152600e60248201526d185b5bdd5b9d0b5a5b9d985b1a5960921b604482015260640161031d565b60008060008061256e61043d565b95509550955050509350808611156125bc5760405162461bcd60e51b8152602060048201526011602482015270195e18d95cdccb5dda5d1a191c985dd85b607a1b604482015260640161031d565b604080516003808252608082019092529060208201606080368337019050509450600a831115612611576125f08684612bad565b8660008151811061260357612603613321565b602090810291909101015295505b600a821180156126215750600086115b15612651576126308683612bad565b8660018151811061264357612643613321565b602090810291909101015295505b600a841180156126615750600086115b15612691576126708685612bad565b8660028151811061268357612683613321565b602090810291909101015295505b50505050919050565b81816000815181106126ae576126ae613321565b602002602001015114156126c0575050565b6000816002815181106126d5576126d5613321565b6020026020010151826001815181106126f0576126f0613321565b60200260200101518360008151811061270b5761270b613321565b602002602001015161271d9190613108565b6127279190613108565b905080831461276e5760405162461bcd60e51b81526020600482015260136024820152721d1c985b9cd9995c9ccb5b9bdd0b5d985b1a59606a1b604482015260640161031d565b60008060008460028151811061278657612786613321565b6020026020010151856001815181106127a1576127a1613321565b60200260200101516127b39190613108565b90506000856002815181106127ca576127ca613321565b602002602001015111156127e657816127e2816132f0565b9250505b80156127fa57816127f6816132f0565b9250505b60008267ffffffffffffffff81111561281557612815613337565b60405190808252806020026020018201604052801561284857816020015b60608152602001906001900390816128335790505b50905060008367ffffffffffffffff81111561286657612866613337565b60405190808252806020026020018201604052801561289957816020015b60608152602001906001900390816128845790505b5090506000876002815181106128b1576128b1613321565b602002602001015111156129985760405180604001604052806009815260200168414156452d56322d4160b81b8152508286815181106128f3576128f3613321565b602090810291909101015260675487516001600160a01b03909116908890600290811061292257612922613321565b60200260200101516000806040516024016129409493929190612fcc565b60408051601f198184030181529190526020810180516001600160e01b03166322996bbb60e11b179052815182908790811061297e5761297e613321565b60200260200101819052508480612994906132f0565b9550505b8215612a4a576040518060400160405280600781526020016642415349432d4160c81b8152508286815181106129d0576129d0613321565b6020908102919091010152606754604051612a00916001600160a01b031690859030906000908190602401612f96565b60408051601f198184030181529190526020810180516001600160e01b03166325e9d5c160e11b1790528151829087908110612a3e57612a3e613321565b60200260200101819052505b606a546040516324c1324d60e21b81526001600160a01b0390911690639304c93490612a7e90859085903090600401612ff8565b602060405180830381600087803b158015612a9857600080fd5b505af1158015612aac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad09190612e9f565b505050505050505050565b6000612b30826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612bda9092919063ffffffff16565b8051909150156123ca5780806020019051810190612b4e9190612e7d565b6123ca5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161031d565b600080600084841115612bc35750600093612bd2565b5082612bcf8186613272565b94505b939492505050565b6060612be98484600085612bf1565b949350505050565b606082471015612c525760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161031d565b6001600160a01b0385163b612ca95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161031d565b600080866001600160a01b03168587604051612cc59190612f7a565b60006040518083038185875af1925050503d8060008114612d02576040519150601f19603f3d011682016040523d82523d6000602084013e612d07565b606091505b5091509150612d17828286612d22565b979650505050505050565b60608315612d3157508161059f565b825115612d415782518084602001fd5b8160405162461bcd60e51b815260040161031d91906130be565b600060208284031215612d6d57600080fd5b813561059f8161334d565b600060208284031215612d8a57600080fd5b815161059f8161334d565b60008060408385031215612da857600080fd5b8235612db38161334d565b91506020830135612dc38161334d565b809150509250929050565b600080600060608486031215612de357600080fd5b8335612dee8161334d565b92506020840135612dfe8161334d565b929592945050506040919091013590565b60008060408385031215612e2257600080fd5b8235612e2d8161334d565b946020939093013593505050565b600080600060608486031215612e5057600080fd5b8335612e5b8161334d565b9250602084013591506040840135612e728161334d565b809150509250925092565b600060208284031215612e8f57600080fd5b8151801515811461059f57600080fd5b600060208284031215612eb157600080fd5b5051919050565b600060208284031215612eca57600080fd5b5035919050565b60008060408385031215612ee457600080fd5b823591506020830135612dc38161334d565b600080600060608486031215612f0b57600080fd5b83359250602084013591506040840135612e728161334d565b600060208284031215612f3657600080fd5b815167ffffffffffffffff8116811461059f57600080fd5b60008151808452612f66816020860160208601613289565b601f01601f19169290920160200192915050565b60008251612f8c818460208701613289565b9190910192915050565b6001600160a01b039586168152602081019490945291909316604083015260ff9283166060830152909116608082015260a00190565b6001600160a01b03949094168452602084019290925260ff908116604084015216606082015260800190565b6000606082016060835280865180835260808501915060808160051b8601019250602080890160005b8381101561304f57607f1988870301855261303d868351612f4e565b95509382019390820190600101613021565b505085840381870152875180855281850193509150600582901b8401810188820160005b848110156130a157601f1987840301865261308f838351612f4e565b95840195925090830190600101613073565b50506001600160a01b03881660408801529450612be99350505050565b60208152600061059f6020830184612f4e565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6000821982111561311b5761311b61330b565b500190565b60008261313d57634e487b7160e01b600052601260045260246000fd5b500490565b600181815b8085111561317d5781600019048211156131635761316361330b565b8085161561317057918102915b93841c9390800290613147565b509250929050565b600061059f60ff84168360008261319e57506001610437565b816131ab57506000610437565b81600181146131c157600281146131cb576131e7565b6001915050610437565b60ff8411156131dc576131dc61330b565b50506001821b610437565b5060208310610133831016604e8410600b841016171561320a575081810a610437565b6132148383613142565b80600019048211156132285761322861330b565b029392505050565b600081600019048311821515161561324a5761324a61330b565b500290565b600061ffff8381169083168181101561326a5761326a61330b565b039392505050565b6000828210156132845761328461330b565b500390565b60005b838110156132a457818101518382015260200161328c565b838111156117845750506000910152565b600181811c908216806132c957607f821691505b602082108114156132ea57634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156133045761330461330b565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461336257600080fd5b5056fea2646970667358221220393338cf4fa7412273740334cbc4dd411d569395435b47e3dc9f027d51e33e0f64736f6c63430008060033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ 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.