Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
Latest 23 from a total of 23 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Set Controller | 18901365 | 274 days ago | IN | 0 ETH | 0.00047303 | ||||
Execute For Acco... | 18901364 | 274 days ago | IN | 0 ETH | 0.00286779 | ||||
Set Controller | 18901363 | 274 days ago | IN | 0 ETH | 0.00047724 | ||||
Set Controller | 18901317 | 274 days ago | IN | 0 ETH | 0.00050293 | ||||
Execute For Acco... | 18901316 | 274 days ago | IN | 0 ETH | 0.00378411 | ||||
Get Total | 18892990 | 275 days ago | IN | 0 ETH | 0.00202708 | ||||
Set Controller | 18814394 | 286 days ago | IN | 0 ETH | 0.00180776 | ||||
Set Controller | 18814372 | 286 days ago | IN | 0 ETH | 0.00215039 | ||||
Set Controller | 18814366 | 286 days ago | IN | 0 ETH | 0.00206709 | ||||
Set Controller | 18814332 | 286 days ago | IN | 0 ETH | 0.00199836 | ||||
Set Controller | 18814322 | 286 days ago | IN | 0 ETH | 0.00228025 | ||||
Set Controller | 18543790 | 324 days ago | IN | 0 ETH | 0.00171325 | ||||
Set Controller | 18543773 | 324 days ago | IN | 0 ETH | 0.00166335 | ||||
Set Paused State | 14656850 | 888 days ago | IN | 0 ETH | 0.00157574 | ||||
Set Paused State | 14655720 | 888 days ago | IN | 0 ETH | 0.00237944 | ||||
Set Paused State | 11872079 | 1320 days ago | IN | 0 ETH | 0.00409234 | ||||
Set Referral Cod... | 11869221 | 1321 days ago | IN | 0 ETH | 0.0065627 | ||||
Set Paused State | 11860357 | 1322 days ago | IN | 0 ETH | 0.0029243 | ||||
Set Aave Bridge | 11860303 | 1322 days ago | IN | 0 ETH | 0.00402174 | ||||
Set Controller | 11860303 | 1322 days ago | IN | 0 ETH | 0.00401112 | ||||
Set Paused State | 11860171 | 1322 days ago | IN | 0 ETH | 0.0014616 | ||||
Set Paused State | 11860061 | 1322 days ago | IN | 0 ETH | 0.00486673 | ||||
0x60806040 | 11859948 | 1322 days ago | IN | 0 ETH | 0.45720991 |
Latest 25 internal transactions (View All)
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:
AaveWalletManager
Compiler Version
v0.6.12+commit.27d51765
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // AaveWalletManager.sol -- Part of the Charged Particles Protocol // Copyright (c) 2021 Firma Lux, Inc. <https://charged.fi> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. pragma solidity 0.6.12; import "@openzeppelin/contracts/math/SafeMath.sol"; import "../../lib/WalletManagerBase.sol"; import "./AaveSmartWallet.sol"; /** * @notice Wallet Manager for Aave * @dev Non-upgradeable Contract */ contract AaveWalletManager is WalletManagerBase { using SafeMath for uint256; event AaveBridgeSet(address indexed aaveBridge); event ValidRewardsTokenSet(address indexed rewardsToken, bool state); address internal _aaveBridge; uint256 internal _referralCode; mapping (address => bool) public rewardsTokenWhitelist; /***********************************| | Initialization | |__________________________________*/ constructor () public { _walletTemplate = address(new AaveSmartWallet()); } /***********************************| | Public | |__________________________________*/ function isReserveActive(address contractAddress, uint256 tokenId, address assetToken) external view override returns (bool) { uint256 uuid = contractAddress.getTokenUUID(tokenId); if (_wallets[uuid] == address(0x0)) { return false; } return AaveSmartWallet(_wallets[uuid]).isReserveActive(assetToken); } function getReserveInterestToken(address contractAddress, uint256 tokenId, address assetToken) external view override returns (address) { uint256 uuid = contractAddress.getTokenUUID(tokenId); if (_wallets[uuid] == address(0x0)) { return address(0x0); } return AaveSmartWallet(_wallets[uuid]).getReserveInterestToken(assetToken); } /** * @notice Gets the Principal-Amount of Assets held in the Smart-Wallet * @param contractAddress The Address to the External Contract of the Token * @param tokenId The ID of the Token within the External Contract * @return The Principal-Balance of the Smart-Wallet */ function getPrincipal(address contractAddress, uint256 tokenId, address assetToken) external override returns (uint256) { uint256 uuid = contractAddress.getTokenUUID(tokenId); if (_wallets[uuid] == address(0x0)) { return 0; } return AaveSmartWallet(_wallets[uuid]).getPrincipal(assetToken); } /** * @notice Gets the Interest-Amount that the Token has generated * @param contractAddress The Address to the External Contract of the Token * @param tokenId The ID of the Token within the External Contract * @return creatorInterest The NFT Creator's portion of the Interest * @return ownerInterest The NFT Owner's portion of the Interest */ function getInterest(address contractAddress, uint256 tokenId, address assetToken) external override returns (uint256 creatorInterest, uint256 ownerInterest) { uint256 uuid = contractAddress.getTokenUUID(tokenId); if (_wallets[uuid] != address(0x0)) { return AaveSmartWallet(_wallets[uuid]).getInterest(assetToken); } } /** * @notice Gets the Available Balance of Assets held in the Token * @param contractAddress The Address to the External Contract of the Token * @param tokenId The ID of the Token within the External Contract * @return The Available Balance of the Token */ function getTotal(address contractAddress, uint256 tokenId, address assetToken) external override returns (uint256) { uint256 uuid = contractAddress.getTokenUUID(tokenId); if (_wallets[uuid] == address(0x0)) { return 0; } return AaveSmartWallet(_wallets[uuid]).getTotal(assetToken); } function getRewards(address contractAddress, uint256 tokenId, address _rewardToken) external override returns (uint256) { uint256 uuid = contractAddress.getTokenUUID(tokenId); if (_wallets[uuid] == address(0x0)) { return 0; } return AaveSmartWallet(_wallets[uuid]).getRewards(_rewardToken); } /***********************************| | Only Controller | |__________________________________*/ function energize( address contractAddress, uint256 tokenId, address assetToken, uint256 assetAmount ) external override onlyController returns (uint256 yieldTokensAmount) { uint256 uuid = contractAddress.getTokenUUID(tokenId); address wallet = _wallets[uuid]; // Deposit into Smart-Wallet yieldTokensAmount = AaveSmartWallet(wallet).deposit(assetToken, assetAmount, _referralCode); // Log Event emit WalletEnergized(contractAddress, tokenId, assetToken, assetAmount, yieldTokensAmount); } function discharge( address receiver, address contractAddress, uint256 tokenId, address assetToken, address creatorRedirect ) external override onlyController returns (uint256 creatorAmount, uint256 receiverAmount) { uint256 uuid = contractAddress.getTokenUUID(tokenId); address wallet = _wallets[uuid]; require(wallet != address(0x0), "AWM:E-403"); (, uint256 ownerInterest) = AaveSmartWallet(wallet).getInterest(assetToken); require(ownerInterest > 0, "AWM:E-412"); // Discharge the full amount of interest (creatorAmount, receiverAmount) = AaveSmartWallet(wallet).withdrawAmount(receiver, creatorRedirect, assetToken, ownerInterest); // Log Event emit WalletDischarged(contractAddress, tokenId, assetToken, creatorAmount, receiverAmount); } function dischargeAmount( address receiver, address contractAddress, uint256 tokenId, address assetToken, uint256 assetAmount, address creatorRedirect ) external override onlyController returns (uint256 creatorAmount, uint256 receiverAmount) { uint256 uuid = contractAddress.getTokenUUID(tokenId); address wallet = _wallets[uuid]; require(wallet != address(0x0), "AWM:E-403"); (, uint256 ownerInterest) = AaveSmartWallet(wallet).getInterest(assetToken); require(assetAmount > 0 && ownerInterest >= assetAmount, "AWM:E-412"); // Discharge a portion of the interest (creatorAmount, receiverAmount) = AaveSmartWallet(wallet).withdrawAmount(receiver, creatorRedirect, assetToken, assetAmount); // Log Event emit WalletDischarged(contractAddress, tokenId, assetToken, creatorAmount, receiverAmount); } function dischargeAmountForCreator( address receiver, address contractAddress, uint256 tokenId, address creator, address assetToken, uint256 assetAmount ) external override onlyController returns (uint256 receiverAmount) { uint256 uuid = contractAddress.getTokenUUID(tokenId); address wallet = _wallets[uuid]; require(wallet != address(0x0), "AWM:E-403"); (uint256 creatorInterest,) = AaveSmartWallet(wallet).getInterest(assetToken); require(assetAmount > 0 && creatorInterest >= assetAmount, "AWM:E-412"); // Discharge a portion of the interest receiverAmount = AaveSmartWallet(wallet).withdrawAmountForCreator(receiver, assetToken, assetAmount); // Log Event emit WalletDischargedForCreator(contractAddress, tokenId, assetToken, creator, receiverAmount); } function release( address receiver, address contractAddress, uint256 tokenId, address assetToken, address creatorRedirect ) external override onlyController returns (uint256 principalAmount, uint256 creatorAmount, uint256 receiverAmount) { uint256 uuid = contractAddress.getTokenUUID(tokenId); address wallet = _wallets[uuid]; require(wallet != address(0x0), "AWM:E-403"); // Release Principal + Interest principalAmount = AaveSmartWallet(wallet).getPrincipal(assetToken); (creatorAmount, receiverAmount) = AaveSmartWallet(wallet).withdraw(receiver, creatorRedirect, assetToken); // Log Event emit WalletReleased(contractAddress, tokenId, receiver, assetToken, principalAmount, creatorAmount, receiverAmount); } function releaseAmount( address receiver, address contractAddress, uint256 tokenId, address assetToken, uint256 assetAmount, address creatorRedirect ) external override onlyController returns (uint256 principalAmount, uint256 creatorAmount, uint256 receiverAmount) { uint256 uuid = contractAddress.getTokenUUID(tokenId); address wallet = _wallets[uuid]; require(wallet != address(0x0), "AWM:E-403"); (, uint256 ownerInterest) = AaveSmartWallet(wallet).getInterest(assetToken); principalAmount = (ownerInterest < assetAmount) ? assetAmount.sub(ownerInterest) : 0; // Release from interest first + principal if needed (creatorAmount, receiverAmount) = AaveSmartWallet(wallet).withdrawAmount(receiver, creatorRedirect, assetToken, assetAmount); // Log Event emit WalletReleased(contractAddress, tokenId, receiver, assetToken, principalAmount, creatorAmount, receiverAmount); } function withdrawRewards( address receiver, address contractAddress, uint256 tokenId, address rewardsToken, uint256 rewardsAmount ) external override onlyController returns (uint256 amount) { uint256 uuid = contractAddress.getTokenUUID(tokenId); address wallet = _wallets[uuid]; require(wallet != address(0x0), "AWM:E-403"); require(rewardsTokenWhitelist[rewardsToken], "AWM:E-423"); // Withdraw Rewards to Receiver amount = AaveSmartWallet(wallet).withdrawRewards(receiver, rewardsToken, rewardsAmount); // Log Event emit WalletRewarded(contractAddress, tokenId, receiver, rewardsToken, amount); } function executeForAccount( address contractAddress, uint256 tokenId, address externalAddress, uint256 ethValue, bytes memory encodedParams ) external override onlyController returns (bytes memory) { uint256 uuid = contractAddress.getTokenUUID(tokenId); address wallet = _wallets[uuid]; return AaveSmartWallet(wallet).executeForAccount(externalAddress, ethValue, encodedParams); } function getWalletAddressById( address contractAddress, uint256 tokenId, address creator, uint256 annuityPct ) external override onlyController returns (address) { uint256 uuid = contractAddress.getTokenUUID(tokenId); address wallet = _wallets[uuid]; // Create Smart-Wallet if none exists if (wallet == address(0x0)) { wallet = _createWallet(); _wallets[uuid] = wallet; if (creator != address(0x0)) { AaveSmartWallet(wallet).setNftCreator(creator, annuityPct); } emit NewSmartWallet(contractAddress, tokenId, wallet, creator, annuityPct); } return wallet; } /***********************************| | Only Admin/DAO | |__________________________________*/ function setAaveBridge(address aaveBridge) external onlyOwner { require(aaveBridge != address(0x0), "AWM:E-403"); _aaveBridge = aaveBridge; emit AaveBridgeSet(aaveBridge); } // ref: https://docs.aave.com/developers/developing-on-aave/the-protocol/lendingpool function setReferralCode(uint256 referralCode) external onlyOwner { _referralCode = referralCode; } function setValidRewardsToken(address rewardsToken, bool state) external onlyOwner { rewardsTokenWhitelist[rewardsToken] = state; emit ValidRewardsTokenSet(rewardsToken, state); } /***********************************| | Private Functions | |__________________________________*/ function _createWallet() internal returns (address) { address newWallet = _createClone(_walletTemplate); AaveSmartWallet(newWallet).initialize(_aaveBridge); return newWallet; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT // WalletManagerBase.sol -- Part of the Charged Particles Protocol // Copyright (c) 2021 Firma Lux, Inc. <https://charged.fi> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. pragma solidity >=0.6.0; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../interfaces/IWalletManager.sol"; import "../interfaces/ISmartWallet.sol"; import "../lib/TokenInfo.sol"; import "./BlackholePrevention.sol"; /** * @notice Wallet-Manager Base Contract * @dev Non-upgradeable Contract */ abstract contract WalletManagerBase is Ownable, BlackholePrevention, IWalletManager { using TokenInfo for address; // The Controller Contract Address address internal _controller; // Template Contract for creating Token Smart-Wallet Bridges address internal _walletTemplate; // TokenID => Token Smart-Wallet Address mapping (uint256 => address) internal _wallets; // State of Wallet Manager bool internal _paused; /***********************************| | Public | |__________________________________*/ function isPaused() external view override returns (bool) { return _paused; } /***********************************| | Only Admin/DAO | |__________________________________*/ /** * @dev Sets the Paused-state of the Wallet Manager */ function setPausedState(bool paused) external onlyOwner { _paused = paused; emit PausedStateSet(paused); } /** * @dev Connects to the Charged Particles Controller */ function setController(address controller) external onlyOwner { _controller = controller; emit ControllerSet(controller); } function withdrawEther(address contractAddress, uint256 tokenId, address payable receiver, uint256 amount) external virtual override onlyOwner { uint256 uuid = contractAddress.getTokenUUID(tokenId); address wallet = _wallets[uuid]; _withdrawEther(receiver, amount); return ISmartWallet(wallet).withdrawEther(receiver, amount); } function withdrawERC20(address contractAddress, uint256 tokenId, address payable receiver, address tokenAddress, uint256 amount) external virtual override onlyOwner { uint256 uuid = contractAddress.getTokenUUID(tokenId); address wallet = _wallets[uuid]; _withdrawERC20(receiver, tokenAddress, amount); return ISmartWallet(wallet).withdrawERC20(receiver, tokenAddress, amount); } function withdrawERC721(address contractAddress, uint256 tokenId, address payable receiver, address nftTokenAddress, uint256 nftTokenId) external virtual override onlyOwner { uint256 uuid = contractAddress.getTokenUUID(tokenId); address wallet = _wallets[uuid]; _withdrawERC721(receiver, nftTokenAddress, nftTokenId); return ISmartWallet(wallet).withdrawERC721(receiver, nftTokenAddress, nftTokenId); } /***********************************| | Private Functions | |__________________________________*/ function _getTokenUUID(address contractAddress, uint256 tokenId) internal pure returns (uint256) { return uint256(keccak256(abi.encodePacked(contractAddress, tokenId))); } /** * @dev Creates Contracts from a Template via Cloning * see: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1167.md */ function _createClone(address target) internal returns (address result) { bytes20 targetBytes = bytes20(target); assembly { let clone := mload(0x40) mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) mstore(add(clone, 0x14), targetBytes) mstore(add(clone, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) result := create(0, clone, 0x37) } } /***********************************| | Modifiers | |__________________________________*/ /// @dev Throws if called by any account other than the Controller contract modifier onlyController() { require(_controller == msg.sender, "WMB:E-108"); _; } // Throws if called by any account other than the Charged Particles Escrow Controller. modifier whenNotPaused() { require(_paused != true, "WMB:E-101"); _; } }
// SPDX-License-Identifier: MIT // AaveSmartWallet.sol -- Part of the Charged Particles Protocol // Copyright (c) 2021 Firma Lux, Inc. <https://charged.fi> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. pragma solidity 0.6.12; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "../../interfaces/IAaveBridge.sol"; import "../../lib/SmartWalletBase.sol"; /** * @notice ERC20-Token Smart-Wallet for Aave Assets * @dev Non-upgradeable Contract */ contract AaveSmartWallet is SmartWalletBase { using SafeMath for uint256; using SafeERC20 for IERC20; uint256 constant internal RAY = 1e27; IAaveBridge internal _bridge; /***********************************| | Initialization | |__________________________________*/ function initialize( address aaveBridge ) public { SmartWalletBase.initializeBase(); _bridge = IAaveBridge(aaveBridge); } /***********************************| | Public | |__________________________________*/ function isReserveActive(address assetToken) external view override returns (bool) { return _bridge.isReserveActive(assetToken); } function getReserveInterestToken(address assetToken) external view override returns (address) { return _bridge.getReserveInterestToken(assetToken); } function getPrincipal(address assetToken) external override returns (uint256) { return _getPrincipal(assetToken); } function getInterest(address assetToken) external override returns (uint256 creatorInterest, uint256 ownerInterest) { return _getInterest(assetToken); } function getTotal(address assetToken) external override returns (uint256) { return _getTotal(assetToken); } function getRewards(address rewardToken) external override returns (uint256) { return IERC20(rewardToken).balanceOf(address(this)); } function deposit( address assetToken, uint256 assetAmount, uint256 referralCode ) external override onlyWalletManager returns (uint256) { return _deposit(assetToken, assetAmount, referralCode); } function withdraw( address receiver, address creatorRedirect, address assetToken ) external override onlyWalletManager returns (uint256 creatorAmount, uint256 receiverAmount) { uint256 walletPrincipal = _getPrincipal(assetToken); (, uint256 ownerInterest) = _getInterest(assetToken); return _withdraw(receiver, creatorRedirect, assetToken, walletPrincipal.add(ownerInterest)); } function withdrawAmount( address receiver, address creatorRedirect, address assetToken, uint256 assetAmount ) external override onlyWalletManager returns (uint256 creatorAmount, uint256 receiverAmount) { return _withdraw(receiver, creatorRedirect, assetToken, assetAmount); } function withdrawAmountForCreator( address receiver, address assetToken, uint256 assetAmount ) external override onlyWalletManager returns (uint256 receiverAmount) { return _withdrawForCreator(receiver, assetToken, assetAmount); } function withdrawRewards( address receiver, address rewardsToken, uint256 rewardsAmount ) external override onlyWalletManager returns (uint256) { return _withdrawRewards(receiver, rewardsToken, rewardsAmount); } /***********************************| | Private Functions | |__________________________________*/ function _deposit( address assetToken, uint256 assetAmount, uint256 referralCode ) internal returns (uint256) { _trackAssetToken(assetToken); // Track Principal _assetPrincipalBalance[assetToken] = _assetPrincipalBalance[assetToken].add(assetAmount); // Deposit Assets into Aave (reverts on fail) _sendToken(address(_bridge), assetToken, assetAmount); uint256 aTokensAmount = _bridge.deposit(assetToken, assetAmount, referralCode); // Return amount of aTokens transfered return aTokensAmount; } function _withdraw( address receiver, address creatorRedirect, address assetToken, uint256 assetAmount ) internal returns (uint256 creatorAmount, uint256 receiverAmount) { uint256 walletPrincipal = _getPrincipal(assetToken); (uint256 creatorInterest, uint256 ownerInterest) = _getInterest(assetToken); // Withdraw from Interest only if (assetAmount < ownerInterest) { if (creatorInterest > 0) { uint256 ratio = assetAmount.mul(RAY).div(ownerInterest); creatorAmount = creatorInterest.add(nftCreatorAmountDischarged).mul(ratio).div(RAY); if (creatorAmount <= nftCreatorAmountDischarged) { nftCreatorAmountDischarged = nftCreatorAmountDischarged.sub(creatorAmount); creatorAmount = 0; } else { creatorAmount = creatorAmount.sub(nftCreatorAmountDischarged); nftCreatorAmountDischarged = 0; } } receiverAmount = assetAmount; } // Withdraw from Interest + Principal else { uint256 fromPrincipal = assetAmount.sub(ownerInterest); if (fromPrincipal > walletPrincipal) { fromPrincipal = walletPrincipal.sub(ownerInterest); } creatorAmount = creatorInterest; receiverAmount = ownerInterest.add(fromPrincipal); nftCreatorAmountDischarged = 0; // Track Principal _assetPrincipalBalance[assetToken] = _assetPrincipalBalance[assetToken].sub(fromPrincipal); } // Send aTokens to Bridge address aTokenAddress = _bridge.getReserveInterestToken(assetToken); _sendToken(address(_bridge), aTokenAddress, receiverAmount.add(creatorAmount)); // Withdraw Assets for Creator if (creatorAmount > 0) { address receivesForCreator = (creatorRedirect != address(0x0)) ? creatorRedirect : nftCreator; _bridge.withdraw(receivesForCreator, assetToken, creatorAmount); } // Withdraw Assets for Receiver _bridge.withdraw(receiver, assetToken, receiverAmount); } function _withdrawForCreator( address receiver, address assetToken, uint256 assetAmount ) internal returns (uint256 receiverAmount) { (uint256 creatorInterest,) = _getInterest(assetToken); if (creatorInterest == 0) { return 0; } if (assetAmount > creatorInterest) { assetAmount = creatorInterest; } nftCreatorAmountDischarged = nftCreatorAmountDischarged.add(assetAmount); // Send aTokens to Bridge address aTokenAddress = _bridge.getReserveInterestToken(assetToken); _sendToken(address(_bridge), aTokenAddress, assetAmount); // Withdraw Assets for Receiver on behalf of Creator _bridge.withdraw(receiver, assetToken, assetAmount); } function _withdrawRewards( address receiver, address rewardsTokenAddress, uint256 rewardsAmount ) internal returns (uint256) { address self = address(this); IERC20 rewardsToken = IERC20(rewardsTokenAddress); uint256 walletBalance = rewardsToken.balanceOf(self); require(walletBalance >= rewardsAmount, "ASW:E-411"); // Transfer Rewards to Receiver rewardsToken.safeTransfer(receiver, rewardsAmount); return rewardsAmount; } function _getTotal(address assetToken) internal view returns (uint256) { return _bridge.getTotalBalance(address(this), assetToken); } function _getInterest(address assetToken) internal view returns (uint256 creatorInterest, uint256 ownerInterest) { uint256 total = _getTotal(assetToken); uint256 principal = _getPrincipal(assetToken); uint256 interest = total.sub(principal); // Creator Royalties if (nftCreatorAnnuityPct > 0) { // Interest too small to calculate percentage; if (interest <= PERCENTAGE_SCALE) { // creatorInterest = interest.div(2); // split evenly? creatorInterest = 0; // All to owner } // Calculate percentage for Creator else { creatorInterest = interest .add(nftCreatorAmountDischarged) .mul(nftCreatorAnnuityPct) .div(PERCENTAGE_SCALE) .sub(nftCreatorAmountDischarged); } } // Owner Portion ownerInterest = interest.sub(creatorInterest); } function _sendToken(address to, address token, uint256 amount) internal { IERC20(token).safeTransfer(to, amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; import "../GSN/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(_owner == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT // IWalletManager.sol -- Part of the Charged Particles Protocol // Copyright (c) 2021 Firma Lux, Inc. <https://charged.fi> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. pragma solidity >=0.6.0; /** * @title Particle Wallet Manager interface * @dev The wallet-manager for underlying assets attached to Charged Particles * @dev Manages the link between NFTs and their respective Smart-Wallets */ interface IWalletManager { event ControllerSet(address indexed controller); event PausedStateSet(bool isPaused); event NewSmartWallet(address indexed contractAddress, uint256 indexed tokenId, address indexed smartWallet, address creator, uint256 annuityPct); event WalletEnergized(address indexed contractAddress, uint256 indexed tokenId, address indexed assetToken, uint256 assetAmount, uint256 yieldTokensAmount); event WalletDischarged(address indexed contractAddress, uint256 indexed tokenId, address indexed assetToken, uint256 creatorAmount, uint256 receiverAmount); event WalletDischargedForCreator(address indexed contractAddress, uint256 indexed tokenId, address indexed assetToken, address creator, uint256 receiverAmount); event WalletReleased(address indexed contractAddress, uint256 indexed tokenId, address indexed receiver, address assetToken, uint256 principalAmount, uint256 creatorAmount, uint256 receiverAmount); event WalletRewarded(address indexed contractAddress, uint256 indexed tokenId, address indexed receiver, address rewardsToken, uint256 rewardsAmount); function isPaused() external view returns (bool); function isReserveActive(address contractAddress, uint256 tokenId, address assetToken) external view returns (bool); function getReserveInterestToken(address contractAddress, uint256 tokenId, address assetToken) external view returns (address); function getTotal(address contractAddress, uint256 tokenId, address assetToken) external returns (uint256); function getPrincipal(address contractAddress, uint256 tokenId, address assetToken) external returns (uint256); function getInterest(address contractAddress, uint256 tokenId, address assetToken) external returns (uint256 creatorInterest, uint256 ownerInterest); function getRewards(address contractAddress, uint256 tokenId, address rewardToken) external returns (uint256); function energize(address contractAddress, uint256 tokenId, address assetToken, uint256 assetAmount) external returns (uint256 yieldTokensAmount); function discharge(address receiver, address contractAddress, uint256 tokenId, address assetToken, address creatorRedirect) external returns (uint256 creatorAmount, uint256 receiverAmount); function dischargeAmount(address receiver, address contractAddress, uint256 tokenId, address assetToken, uint256 assetAmount, address creatorRedirect) external returns (uint256 creatorAmount, uint256 receiverAmount); function dischargeAmountForCreator(address receiver, address contractAddress, uint256 tokenId, address creator, address assetToken, uint256 assetAmount) external returns (uint256 receiverAmount); function release(address receiver, address contractAddress, uint256 tokenId, address assetToken, address creatorRedirect) external returns (uint256 principalAmount, uint256 creatorAmount, uint256 receiverAmount); function releaseAmount(address receiver, address contractAddress, uint256 tokenId, address assetToken, uint256 assetAmount, address creatorRedirect) external returns (uint256 principalAmount, uint256 creatorAmount, uint256 receiverAmount); function withdrawRewards(address receiver, address contractAddress, uint256 tokenId, address rewardsToken, uint256 rewardsAmount) external returns (uint256 amount); function executeForAccount(address contractAddress, uint256 tokenId, address externalAddress, uint256 ethValue, bytes memory encodedParams) external returns (bytes memory); function getWalletAddressById(address contractAddress, uint256 tokenId, address creator, uint256 annuityPct) external returns (address); function withdrawEther(address contractAddress, uint256 tokenId, address payable receiver, uint256 amount) external; function withdrawERC20(address contractAddress, uint256 tokenId, address payable receiver, address tokenAddress, uint256 amount) external; function withdrawERC721(address contractAddress, uint256 tokenId, address payable receiver, address nftTokenAddress, uint256 nftTokenId) external; }
// SPDX-License-Identifier: MIT // ISmartWallet.sol -- Part of the Charged Particles Protocol // Copyright (c) 2021 Firma Lux, Inc. <https://charged.fi> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. pragma solidity >=0.6.0; /** * @title Charged Particles Smart Wallet * @dev Manages holding and transferring assets of an NFT to a specific LP for Yield (if any), */ interface ISmartWallet { function getAssetTokenCount() external view returns (uint256); function getAssetTokenByIndex(uint256 index) external view returns (address); function setNftCreator(address creator, uint256 annuityPct) external; function isReserveActive(address assetToken) external view returns (bool); function getReserveInterestToken(address assetToken) external view returns (address); function getPrincipal(address assetToken) external returns (uint256); function getInterest(address assetToken) external returns (uint256 creatorInterest, uint256 ownerInterest); function getTotal(address assetToken) external returns (uint256); function getRewards(address assetToken) external returns (uint256); function deposit(address assetToken, uint256 assetAmount, uint256 referralCode) external returns (uint256); function withdraw(address receiver, address creatorRedirect, address assetToken) external returns (uint256 creatorAmount, uint256 receiverAmount); function withdrawAmount(address receiver, address creatorRedirect, address assetToken, uint256 assetAmount) external returns (uint256 creatorAmount, uint256 receiverAmount); function withdrawAmountForCreator(address receiver, address assetToken, uint256 assetAmount) external returns (uint256 receiverAmount); function withdrawRewards(address receiver, address rewardsToken, uint256 rewardsAmount) external returns (uint256); function executeForAccount(address contractAddress, uint256 ethValue, bytes memory encodedParams) external returns (bytes memory); function withdrawEther(address payable receiver, uint256 amount) external; function withdrawERC20(address payable receiver, address tokenAddress, uint256 amount) external; function withdrawERC721(address payable receiver, address tokenAddress, uint256 tokenId) external; }
// SPDX-License-Identifier: MIT // TokenInfo.sol -- Part of the Charged Particles Protocol // Copyright (c) 2021 Firma Lux, Inc. <https://charged.fi> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. pragma solidity 0.6.12; import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import "../interfaces/IERC721Chargeable.sol"; library TokenInfo { function getTokenUUID(address contractAddress, uint256 tokenId) internal pure virtual returns (uint256) { return uint256(keccak256(abi.encodePacked(contractAddress, tokenId))); } function getTokenOwner(address contractAddress, uint256 tokenId) internal view virtual returns (address) { IERC721Chargeable tokenInterface = IERC721Chargeable(contractAddress); return tokenInterface.ownerOf(tokenId); } function getTokenCreator(address contractAddress, uint256 tokenId) internal view virtual returns (address) { IERC721Chargeable tokenInterface = IERC721Chargeable(contractAddress); return tokenInterface.creatorOf(tokenId); } /// @dev Checks if an account is the Owner of an External NFT contract /// @param contractAddress The Address to the Contract of the NFT to check /// @param account The Address of the Account to check /// @return True if the account owns the contract function isContractOwner(address contractAddress, address account) internal view virtual returns (bool) { address contractOwner = IERC721Chargeable(contractAddress).owner(); return contractOwner != address(0x0) && contractOwner == account; } /// @dev Checks if an account is the Creator of a Proton-based NFT /// @param contractAddress The Address to the Contract of the Proton-based NFT to check /// @param tokenId The Token ID of the Proton-based NFT to check /// @param sender The Address of the Account to check /// @return True if the account is the creator of the Proton-based NFT function isTokenCreator(address contractAddress, uint256 tokenId, address sender) internal view virtual returns (bool) { IERC721Chargeable tokenInterface = IERC721Chargeable(contractAddress); address tokenCreator = tokenInterface.creatorOf(tokenId); return (sender == tokenCreator); } /// @dev Checks if an account is the Creator of a Proton-based NFT or the Contract itself /// @param contractAddress The Address to the Contract of the Proton-based NFT to check /// @param tokenId The Token ID of the Proton-based NFT to check /// @param sender The Address of the Account to check /// @return True if the account is the creator of the Proton-based NFT or the Contract itself function isTokenContractOrCreator(address contractAddress, uint256 tokenId, address creator, address sender) internal view virtual returns (bool) { IERC721Chargeable tokenInterface = IERC721Chargeable(contractAddress); address tokenCreator = tokenInterface.creatorOf(tokenId); if (sender == contractAddress && creator == tokenCreator) { return true; } return (sender == tokenCreator); } /// @dev Checks if an account is the Owner or Operator of an External NFT /// @param contractAddress The Address to the Contract of the External NFT to check /// @param tokenId The Token ID of the External NFT to check /// @param sender The Address of the Account to check /// @return True if the account is the Owner or Operator of the External NFT function isErc721OwnerOrOperator(address contractAddress, uint256 tokenId, address sender) internal view virtual returns (bool) { IERC721Chargeable tokenInterface = IERC721Chargeable(contractAddress); address tokenOwner = tokenInterface.ownerOf(tokenId); return (sender == tokenOwner || tokenInterface.isApprovedForAll(tokenOwner, sender)); } /** * @dev Returns true if `account` is a contract. * @dev Taken from OpenZeppelin library * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * @dev Taken from OpenZeppelin library * * 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, "TokenInfo: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "TokenInfo: unable to send value, recipient may have reverted"); } }
// SPDX-License-Identifier: MIT // BlackholePrevention.sol -- Part of the Charged Particles Protocol // Copyright (c) 2021 Firma Lux, Inc. <https://charged.fi> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. pragma solidity >=0.6.0; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; /** * @notice Prevents ETH or Tokens from getting stuck in a contract by allowing * the Owner/DAO to pull them out on behalf of a user * This is only meant to contracts that are not expected to hold tokens, but do handle transferring them. */ contract BlackholePrevention { using Address for address payable; using SafeERC20 for IERC20; event WithdrawStuckEther(address indexed receiver, uint256 amount); event WithdrawStuckERC20(address indexed receiver, address indexed tokenAddress, uint256 amount); event WithdrawStuckERC721(address indexed receiver, address indexed tokenAddress, uint256 indexed tokenId); function _withdrawEther(address payable receiver, uint256 amount) internal virtual { require(receiver != address(0x0), "BHP:E-403"); if (address(this).balance >= amount) { receiver.sendValue(amount); emit WithdrawStuckEther(receiver, amount); } } function _withdrawERC20(address payable receiver, address tokenAddress, uint256 amount) internal virtual { require(receiver != address(0x0), "BHP:E-403"); if (IERC20(tokenAddress).balanceOf(address(this)) >= amount) { IERC20(tokenAddress).safeTransfer(receiver, amount); emit WithdrawStuckERC20(receiver, tokenAddress, amount); } } function _withdrawERC721(address payable receiver, address tokenAddress, uint256 tokenId) internal virtual { require(receiver != address(0x0), "BHP:E-403"); if (IERC721(tokenAddress).ownerOf(tokenId) == address(this)) { IERC721(tokenAddress).transferFrom(address(this), receiver, tokenId); emit WithdrawStuckERC721(receiver, tokenAddress, tokenId); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @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 `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT // IERC721Chargeable.sol -- Part of the Charged Particles Protocol // Copyright (c) 2021 Firma Lux, Inc. <https://charged.fi> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. pragma solidity >=0.6.0; import "@openzeppelin/contracts-upgradeable/introspection/IERC165Upgradeable.sol"; interface IERC721Chargeable is IERC165Upgradeable { function owner() external view returns (address); function creatorOf(uint256 tokenId) external view returns (address); function balanceOf(address tokenOwner) external view returns (uint256 balance); function ownerOf(uint256 tokenId) external view returns (address tokenOwner); function safeTransferFrom(address from, address to, uint256 tokenId) external; function transferFrom(address from, address to, uint256 tokenId) external; function approve(address to, uint256 tokenId) external; function getApproved(uint256 tokenId) external view returns (address operator); function setApprovalForAll(address operator, bool _approved) external; function isApprovedForAll(address tokenOwner, address operator) external view returns (bool); function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.2; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return _functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); return _functionCallWithValue(target, data, value, errorMessage); } function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; import "./IERC20.sol"; import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.2; import "../../introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transfered from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // IAaveBridge.sol -- Part of the Charged Particles Protocol // Copyright (c) 2021 Firma Lux, Inc. <https://charged.fi> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. pragma solidity >=0.6.0; interface IAaveBridge { function getReserveInterestToken(address assetToken) external view returns (address aTokenAddress); function isReserveActive(address assetToken) external view returns (bool); function getTotalBalance(address account, address assetToken) external view returns (uint256); function deposit(address assetToken, uint256 assetAmount, uint256 referralCode) external returns (uint256); function withdraw(address receiver, address assetToken, uint256 assetAmount) external; }
// SPDX-License-Identifier: MIT // SmartWalletBase.sol -- Part of the Charged Particles Protocol // Copyright (c) 2021 Firma Lux, Inc. <https://charged.fi> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. pragma solidity >=0.6.0; import "@openzeppelin/contracts/utils/EnumerableSet.sol"; import "../interfaces/ISmartWallet.sol"; import "./BlackholePrevention.sol"; /** * @notice ERC20-Token Smart-Wallet Base Contract * @dev Non-upgradeable Contract */ abstract contract SmartWalletBase is ISmartWallet, BlackholePrevention { using EnumerableSet for EnumerableSet.AddressSet; uint256 constant internal PERCENTAGE_SCALE = 1e4; // 10000 (100%) address internal _walletManager; address internal nftCreator; uint256 internal nftCreatorAnnuityPct; uint256 internal nftCreatorAmountDischarged; EnumerableSet.AddressSet internal _assetTokens; // Asset Token => Principal Balance mapping (address => uint256) internal _assetPrincipalBalance; /***********************************| | Initialization | |__________________________________*/ function initializeBase() public { require(_walletManager == address(0x0), "SWB:E-002"); _walletManager = msg.sender; } /***********************************| | Public | |__________________________________*/ function getAssetTokenCount() external view virtual override returns (uint256) { return _assetTokens.length(); } function getAssetTokenByIndex(uint256 index) external view virtual override returns (address) { if (index >= _assetTokens.length()) { return address(0); } return _assetTokens.at(index); } function setNftCreator(address creator, uint256 annuityPct) external virtual override onlyWalletManager { nftCreator = creator; nftCreatorAnnuityPct = annuityPct; } function executeForAccount( address contractAddress, uint256 ethValue, bytes memory encodedParams ) external override onlyWalletManager returns (bytes memory) { (bool success, bytes memory result) = contractAddress.call{value: ethValue}(encodedParams); require(success, string(result)); return result; } /***********************************| | Only Admin/DAO | | (blackhole prevention) | |__________________________________*/ function withdrawEther(address payable receiver, uint256 amount) external virtual override onlyWalletManager { _withdrawEther(receiver, amount); } function withdrawERC20(address payable receiver, address tokenAddress, uint256 amount) external virtual override onlyWalletManager { _withdrawERC20(receiver, tokenAddress, amount); } function withdrawERC721(address payable receiver, address tokenAddress, uint256 tokenId) external virtual override onlyWalletManager { _withdrawERC721(receiver, tokenAddress, tokenId); } /***********************************| | Private Functions | |__________________________________*/ function _getPrincipal(address assetToken) internal view virtual returns (uint256) { return _assetPrincipalBalance[assetToken]; } function _trackAssetToken(address assetToken) internal virtual { if (!_assetTokens.contains(assetToken)) { _assetTokens.add(assetToken); } } /***********************************| | Modifiers | |__________________________________*/ /// @dev Throws if called by any account other than the wallet manager modifier onlyWalletManager() { require(_walletManager == msg.sender, "SWB:E-109"); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256` * (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping (bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { require(set._values.length > index, "EnumerableSet: index out of bounds"); return set._values[index]; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(value))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(value))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(value))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint256(_at(set._inner, index))); } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"aaveBridge","type":"address"}],"name":"AaveBridgeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"}],"name":"ControllerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"smartWallet","type":"address"},{"indexed":false,"internalType":"address","name":"creator","type":"address"},{"indexed":false,"internalType":"uint256","name":"annuityPct","type":"uint256"}],"name":"NewSmartWallet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isPaused","type":"bool"}],"name":"PausedStateSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rewardsToken","type":"address"},{"indexed":false,"internalType":"bool","name":"state","type":"bool"}],"name":"ValidRewardsTokenSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"assetToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"creatorAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"receiverAmount","type":"uint256"}],"name":"WalletDischarged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"assetToken","type":"address"},{"indexed":false,"internalType":"address","name":"creator","type":"address"},{"indexed":false,"internalType":"uint256","name":"receiverAmount","type":"uint256"}],"name":"WalletDischargedForCreator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"assetToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"assetAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"yieldTokensAmount","type":"uint256"}],"name":"WalletEnergized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"assetToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"principalAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"creatorAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"receiverAmount","type":"uint256"}],"name":"WalletReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"rewardsToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardsAmount","type":"uint256"}],"name":"WalletRewarded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawStuckERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"WithdrawStuckERC721","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawStuckEther","type":"event"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"assetToken","type":"address"},{"internalType":"address","name":"creatorRedirect","type":"address"}],"name":"discharge","outputs":[{"internalType":"uint256","name":"creatorAmount","type":"uint256"},{"internalType":"uint256","name":"receiverAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"assetToken","type":"address"},{"internalType":"uint256","name":"assetAmount","type":"uint256"},{"internalType":"address","name":"creatorRedirect","type":"address"}],"name":"dischargeAmount","outputs":[{"internalType":"uint256","name":"creatorAmount","type":"uint256"},{"internalType":"uint256","name":"receiverAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"address","name":"assetToken","type":"address"},{"internalType":"uint256","name":"assetAmount","type":"uint256"}],"name":"dischargeAmountForCreator","outputs":[{"internalType":"uint256","name":"receiverAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"assetToken","type":"address"},{"internalType":"uint256","name":"assetAmount","type":"uint256"}],"name":"energize","outputs":[{"internalType":"uint256","name":"yieldTokensAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"externalAddress","type":"address"},{"internalType":"uint256","name":"ethValue","type":"uint256"},{"internalType":"bytes","name":"encodedParams","type":"bytes"}],"name":"executeForAccount","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"assetToken","type":"address"}],"name":"getInterest","outputs":[{"internalType":"uint256","name":"creatorInterest","type":"uint256"},{"internalType":"uint256","name":"ownerInterest","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"assetToken","type":"address"}],"name":"getPrincipal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"assetToken","type":"address"}],"name":"getReserveInterestToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"_rewardToken","type":"address"}],"name":"getRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"assetToken","type":"address"}],"name":"getTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"uint256","name":"annuityPct","type":"uint256"}],"name":"getWalletAddressById","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"assetToken","type":"address"}],"name":"isReserveActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"assetToken","type":"address"},{"internalType":"address","name":"creatorRedirect","type":"address"}],"name":"release","outputs":[{"internalType":"uint256","name":"principalAmount","type":"uint256"},{"internalType":"uint256","name":"creatorAmount","type":"uint256"},{"internalType":"uint256","name":"receiverAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"assetToken","type":"address"},{"internalType":"uint256","name":"assetAmount","type":"uint256"},{"internalType":"address","name":"creatorRedirect","type":"address"}],"name":"releaseAmount","outputs":[{"internalType":"uint256","name":"principalAmount","type":"uint256"},{"internalType":"uint256","name":"creatorAmount","type":"uint256"},{"internalType":"uint256","name":"receiverAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardsTokenWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"aaveBridge","type":"address"}],"name":"setAaveBridge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"paused","type":"bool"}],"name":"setPausedState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"referralCode","type":"uint256"}],"name":"setReferralCode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rewardsToken","type":"address"},{"internalType":"bool","name":"state","type":"bool"}],"name":"setValidRewardsToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"address","name":"nftTokenAddress","type":"address"},{"internalType":"uint256","name":"nftTokenId","type":"uint256"}],"name":"withdrawERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"rewardsToken","type":"address"},{"internalType":"uint256","name":"rewardsAmount","type":"uint256"}],"name":"withdrawRewards","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060006200001e620000ba565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506040516200007690620000be565b604051809103906000f08015801562000093573d6000803e3d6000fd5b50600280546001600160a01b0319166001600160a01b0392909216919091179055620000cc565b3390565b611f2680620032fc83390190565b61322080620000dc6000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c806389a5799d116100f9578063c968b02711610097578063f2fde38b11610071578063f2fde38b146107fb578063f314a71e14610821578063fb3642d614610847578063fe34cc3f1461088d576101c4565b8063c968b02714610657578063db9f60ff14610798578063ed452778146107b7576101c4565b806392eefe9b116100d357806392eefe9b146105bd578063a9d16f3b146105e3578063b187bd2614610629578063b5795a9514610631576101c4565b806389a5799d146105315780638b8d9a161461057b5780638da5cb5b146105b5576101c4565b80633d76f93e11610166578063512adb1311610140578063512adb131461043c578063711ad4ec1461048b578063715018a6146104f3578063897f4ecb146104fb576101c4565b80633d76f93e146103585780634737c0c31461039c5780634ff83618146103f2576101c4565b8063238f1b98116101a2578063238f1b981461028557806328644061146102cf5780632be89305146102ec5780632da9ef8114610322576101c4565b806307009629146101c9578063157c5a42146101f9578063235dd2001461023d575b600080fd5b6101f7600480360360408110156101df57600080fd5b506001600160a01b03813516906020013515156108c7565b005b6101f7600480360360a081101561020f57600080fd5b506001600160a01b03813581169160208101359160408201358116916060810135909116906080013561097f565b6102736004803603606081101561025357600080fd5b506001600160a01b03813581169160208101359160409091013516610a9b565b60408051918252519081900360200190f35b6102bb6004803603606081101561029b57600080fd5b506001600160a01b03813581169160208101359160409091013516610b6d565b604080519115158252519081900360200190f35b6101f7600480360360208110156102e557600080fd5b5035610c19565b6102736004803603606081101561030257600080fd5b506001600160a01b03813581169160208101359160409091013516610c76565b6102736004803603606081101561033857600080fd5b506001600160a01b03813581169160208101359160409091013516610d11565b6101f7600480360360a081101561036e57600080fd5b506001600160a01b038135811691602081013591604082013581169160608101359091169060800135610dac565b6103d6600480360360808110156103b257600080fd5b506001600160a01b0381358116916020810135916040820135169060600135610ea7565b604080516001600160a01b039092168252519081900360200190f35b610273600480360360c081101561040857600080fd5b506001600160a01b038135811691602081013582169160408201359160608101358216916080820135169060a00135611042565b6104726004803603606081101561045257600080fd5b506001600160a01b038135811691602081013591604090910135166112b9565b6040805192835260208301919091528051918290030190f35b6104d5600480360360c08110156104a157600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013582169160808201359160a0013516611391565b60408051938452602084019290925282820152519081900360600190f35b6101f76115f2565b6103d66004803603606081101561051157600080fd5b506001600160a01b03813581169160208101359160409091013516611694565b610472600480360360c081101561054757600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013582169160808201359160a001351661172c565b6102736004803603608081101561059157600080fd5b506001600160a01b03813581169160208101359160408201351690606001356119a9565b6103d6611aff565b6101f7600480360360208110156105d357600080fd5b50356001600160a01b0316611b0e565b6104d5600480360360a08110156105f957600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013582169160809091013516611bb0565b6102bb611dea565b6101f76004803603602081101561064757600080fd5b50356001600160a01b0316611df3565b610723600480360360a081101561066d57600080fd5b6001600160a01b0382358116926020810135926040820135909216916060820135919081019060a0810160808201356401000000008111156106ae57600080fd5b8201836020820111156106c057600080fd5b803590602001918460018302840111640100000000831117156106e257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611ee4945050505050565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561075d578181015183820152602001610745565b50505050905090810190601f16801561078a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101f7600480360360208110156107ae57600080fd5b5035151561211b565b610273600480360360a08110156107cd57600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013590911690608001356121ba565b6101f76004803603602081101561081157600080fd5b50356001600160a01b03166123be565b6102bb6004803603602081101561083757600080fd5b50356001600160a01b03166124b6565b610472600480360360a081101561085d57600080fd5b506001600160a01b03813581169160208101358216916040820135916060810135821691608090910135166124cb565b6101f7600480360360808110156108a357600080fd5b506001600160a01b0381358116916020810135916040820135169060600135612739565b6108cf612842565b6000546001600160a01b0390811691161461091f576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b6001600160a01b038216600081815260066020908152604091829020805460ff1916851515908117909155825190815291517f47b3f841cfb31c3cdf247b5ec0118d0ded80f2b51a7c7da0b6da26549e49bd4c9281900390910190a25050565b610987612842565b6000546001600160a01b039081169116146109d7576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b60006109ec6001600160a01b03871686612846565b6000818152600360205260409020549091506001600160a01b0316610a1285858561288a565b806001600160a01b0316634025feb28686866040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b5050505050505050505050565b600080610ab16001600160a01b03861685612846565b6000818152600360205260409020549091506001600160a01b0316610ada576000915050610b66565b60008181526003602090815260408083205481516379ee54f760e01b81526001600160a01b038881166004830152925192909116936379ee54f79360248084019491939192918390030190829087803b158015610b3657600080fd5b505af1158015610b4a573d6000803e3d6000fd5b505050506040513d6020811015610b6057600080fd5b50519150505b9392505050565b600080610b836001600160a01b03861685612846565b6000818152600360205260409020549091506001600160a01b0316610bac576000915050610b66565b60008181526003602090815260409182902054825163883c042b60e01b81526001600160a01b0387811660048301529351939091169263883c042b92602480840193919291829003018186803b158015610c0557600080fd5b505afa158015610b4a573d6000803e3d6000fd5b610c21612842565b6000546001600160a01b03908116911614610c71576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b600555565b600080610c8c6001600160a01b03861685612846565b6000818152600360205260409020549091506001600160a01b0316610cb5576000915050610b66565b6000818152600360209081526040808320548151631d76db5b60e31b81526001600160a01b0388811660048301529251929091169363ebb6dad89360248084019491939192918390030190829087803b158015610b3657600080fd5b600080610d276001600160a01b03861685612846565b6000818152600360205260409020549091506001600160a01b0316610d50576000915050610b66565b6000818152600360209081526040808320548151637abdd2d160e01b81526001600160a01b03888116600483015292519290911693637abdd2d19360248084019491939192918390030190829087803b158015610b3657600080fd5b610db4612842565b6000546001600160a01b03908116911614610e04576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b6000610e196001600160a01b03871686612846565b6000818152600360205260409020549091506001600160a01b0316610e3f858585612a11565b806001600160a01b03166344004cc18686866040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015610a7a57600080fd5b6001546000906001600160a01b03163314610ef5576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b6000610f0a6001600160a01b03871686612846565b6000818152600360205260409020549091506001600160a01b03168061103657610f32612b3b565b600083815260036020526040902080546001600160a01b0319166001600160a01b0383811691909117909155909150851615610fd857806001600160a01b0316636edfab6b86866040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015610fbf57600080fd5b505af1158015610fd3573d6000803e3d6000fd5b505050505b806001600160a01b031686886001600160a01b03167f1cda30153ed04b1a2d5be381fcc3b30f512c22c6f3cbd755b87ad945660a2708888860405180836001600160a01b031681526020018281526020019250505060405180910390a45b9150505b949350505050565b6001546000906001600160a01b03163314611090576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b60006110a56001600160a01b03881687612846565b6000818152600360205260409020549091506001600160a01b0316806110fe576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34303360b81b604482015290519081900360640190fd5b6000816001600160a01b0316637aaa3470876040518263ffffffff1660e01b815260040180826001600160a01b031681526020019150506040805180830381600087803b15801561114e57600080fd5b505af1158015611162573d6000803e3d6000fd5b505050506040513d604081101561117857600080fd5b50519050841580159061118b5750848110155b6111c8576040805162461bcd60e51b815260206004820152600960248201526820aba69d22969a189960b91b604482015290519081900360640190fd5b816001600160a01b03166334115f658b88886040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050602060405180830381600087803b15801561123057600080fd5b505af1158015611244573d6000803e3d6000fd5b505050506040513d602081101561125a57600080fd5b5051604080516001600160a01b038a81168252602082018490528251939750808a16938c93918e16927fc5ee6437398fe6176ea602fb23e08746debd66700cd17f44b17b9214e4778a0a92908290030190a45050509695505050505050565b600080806112d06001600160a01b03871686612846565b6000818152600360205260409020549091506001600160a01b031615611387576000818152600360205260408082205481516307aaa34760e41b81526001600160a01b0388811660048301528351921693637aaa34709360248084019491939192918390030190829087803b15801561134857600080fd5b505af115801561135c573d6000803e3d6000fd5b505050506040513d604081101561137257600080fd5b50805160209091015190935091506113899050565b505b935093915050565b600154600090819081906001600160a01b031633146113e3576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b60006113f86001600160a01b038a1689612846565b6000818152600360205260409020549091506001600160a01b031680611451576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34303360b81b604482015290519081900360640190fd5b6000816001600160a01b0316637aaa34708a6040518263ffffffff1660e01b815260040180826001600160a01b031681526020019150506040805180830381600087803b1580156114a157600080fd5b505af11580156114b5573d6000803e3d6000fd5b505050506040513d60408110156114cb57600080fd5b506020015190508781106114e05760006114ea565b6114ea8882612bd9565b60408051600162e0d48b60e01b031981526001600160a01b038f811660048301528a811660248301528c81166044830152606482018c9052825193995085169263ff1f2b75926084808401939192918290030181600087803b15801561154f57600080fd5b505af1158015611563573d6000803e3d6000fd5b505050506040513d604081101561157957600080fd5b508051602091820151604080516001600160a01b038e811682529481018b9052808201849052606081018390529051929850909650828f16928d92908f16917f9cddee57762ce56bd97afc79f9c6bcd7946b3fe3b43b58b4f944e3190111f423919081900360800190a450505096509650969350505050565b6115fa612842565b6000546001600160a01b0390811691161461164a576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000806116aa6001600160a01b03861685612846565b6000818152600360205260409020549091506001600160a01b03166116d3576000915050610b66565b600081815260036020908152604091829020548251630506601760e51b81526001600160a01b0387811660048301529351939091169263a0cc02e092602480840193919291829003018186803b158015610c0557600080fd5b60015460009081906001600160a01b0316331461177c576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b60006117916001600160a01b03891688612846565b6000818152600360205260409020549091506001600160a01b0316806117ea576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34303360b81b604482015290519081900360640190fd5b6000816001600160a01b0316637aaa3470896040518263ffffffff1660e01b815260040180826001600160a01b031681526020019150506040805180830381600087803b15801561183a57600080fd5b505af115801561184e573d6000803e3d6000fd5b505050506040513d604081101561186457600080fd5b50602001519050861580159061187a5750868110155b6118b7576040805162461bcd60e51b815260206004820152600960248201526820aba69d22969a189960b91b604482015290519081900360640190fd5b60408051600162e0d48b60e01b031981526001600160a01b038d8116600483015288811660248301528a81166044830152606482018a905282519085169263ff1f2b7592608480820193918290030181600087803b15801561191857600080fd5b505af115801561192c573d6000803e3d6000fd5b505050506040513d604081101561194257600080fd5b5080516020918201516040805183815293840182905280519298509096506001600160a01b03808c16938d93918f16927f8c5afa972f06d20ce921881649de0917319195e46b7905b5c3bfeb2ebe62e8bd92918290030190a4505050965096945050505050565b6001546000906001600160a01b031633146119f7576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b6000611a0c6001600160a01b03871686612846565b6000818152600360209081526040808320546005548251630efe6a8b60e01b81526001600160a01b038b81166004830152602482018b90526044820192909252925195965016938493630efe6a8b93606480850194919392918390030190829087803b158015611a7b57600080fd5b505af1158015611a8f573d6000803e3d6000fd5b505050506040513d6020811015611aa557600080fd5b5051604080518681526020810183905281519295506001600160a01b03808916938a93918c16927f888889d6224fdc21d2a6f20b0f8a25cc561b82d8f051c7b471e65903d4d1654d92908290030190a45050949350505050565b6000546001600160a01b031690565b611b16612842565b6000546001600160a01b03908116911614611b66576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517f79f74fd5964b6943d8a1865abfb7f668c92fa3f32c0a2e3195da7d0946703ad790600090a250565b600154600090819081906001600160a01b03163314611c02576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b6000611c176001600160a01b03891688612846565b6000818152600360205260409020549091506001600160a01b031680611c70576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34303360b81b604482015290519081900360640190fd5b806001600160a01b0316637abdd2d1886040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050602060405180830381600087803b158015611cbf57600080fd5b505af1158015611cd3573d6000803e3d6000fd5b505050506040513d6020811015611ce957600080fd5b50516040805160016210ef4360e31b031981526001600160a01b038d8116600483015289811660248301528a81166044830152825193985084169263ff7885e8926064808401939192918290030181600087803b158015611d4957600080fd5b505af1158015611d5d573d6000803e3d6000fd5b505050506040513d6040811015611d7357600080fd5b508051602091820151604080516001600160a01b038c811682529481018a9052808201849052606081018390529051929750909550828d16928b92908d16917f9cddee57762ce56bd97afc79f9c6bcd7946b3fe3b43b58b4f944e3190111f423919081900360800190a45050955095509592505050565b60045460ff1690565b611dfb612842565b6000546001600160a01b03908116911614611e4b576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b6001600160a01b038116611e92576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34303360b81b604482015290519081900360640190fd5b60048054610100600160a81b0319166101006001600160a01b038416908102919091179091556040517f7c96177d7f838426dc6b53224d68914e2500c7f8ef49481c7ccc1d18157a35c090600090a250565b6001546060906001600160a01b03163314611f32576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b6000611f476001600160a01b03881687612846565b600081815260036020908152604080832054905163a18ea08f60e01b81526001600160a01b038a811660048301908152602483018b90526060604484019081528a5160648501528a519798509190931695869563a18ea08f958d958d958d9591949193608490910192860191908190849084905b83811015611fd3578181015183820152602001611fbb565b50505050905090810190601f1680156120005780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561202157600080fd5b505af1158015612035573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561205e57600080fd5b810190808051604051939291908464010000000082111561207e57600080fd5b90830190602082018581111561209357600080fd5b82516401000000008111828201881017156120ad57600080fd5b82525081516020918201929091019080838360005b838110156120da5781810151838201526020016120c2565b50505050905090810190601f1680156121075780820380516001836020036101000a031916815260200191505b506040525050509250505095945050505050565b612123612842565b6000546001600160a01b03908116911614612173576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b6004805482151560ff19909116811790915560408051918252517fa9bfed3d98385b3777389e321dbde773cf7d335fa604fefbae3dca93564f55869181900360200190a150565b6001546000906001600160a01b03163314612208576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b600061221d6001600160a01b03871686612846565b6000818152600360205260409020549091506001600160a01b031680612276576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34303360b81b604482015290519081900360640190fd5b6001600160a01b03851660009081526006602052604090205460ff166122cf576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34323360b81b604482015290519081900360640190fd5b806001600160a01b03166374ee6b628987876040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050602060405180830381600087803b15801561233757600080fd5b505af115801561234b573d6000803e3d6000fd5b505050506040513d602081101561236157600080fd5b5051604080516001600160a01b038881168252602082018490528251939650808c16938a93918c16927f06f54f96ef088b89e726f3399f067502f7f3ab4864f09ba0fd5448eb9d450d3b92908290030190a4505095945050505050565b6123c6612842565b6000546001600160a01b03908116911614612416576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b6001600160a01b03811661245b5760405162461bcd60e51b81526004018080602001828103825260268152602001806131416026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60066020526000908152604090205460ff1681565b60015460009081906001600160a01b0316331461251b576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b60006125306001600160a01b03881687612846565b6000818152600360205260409020549091506001600160a01b031680612589576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34303360b81b604482015290519081900360640190fd5b6000816001600160a01b0316637aaa3470886040518263ffffffff1660e01b815260040180826001600160a01b031681526020019150506040805180830381600087803b1580156125d957600080fd5b505af11580156125ed573d6000803e3d6000fd5b505050506040513d604081101561260357600080fd5b5060200151905080612648576040805162461bcd60e51b815260206004820152600960248201526820aba69d22969a189960b91b604482015290519081900360640190fd5b60408051600162e0d48b60e01b031981526001600160a01b038c81166004830152888116602483015289811660448301526064820184905282519085169263ff1f2b7592608480820193918290030181600087803b1580156126a957600080fd5b505af11580156126bd573d6000803e3d6000fd5b505050506040513d60408110156126d357600080fd5b5080516020918201516040805183815293840182905280519298509096506001600160a01b03808b16938c93918e16927f8c5afa972f06d20ce921881649de0917319195e46b7905b5c3bfeb2ebe62e8bd92918290030190a45050509550959350505050565b612741612842565b6000546001600160a01b03908116911614612791576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b60006127a66001600160a01b03861685612846565b6000818152600360205260409020549091506001600160a01b03166127cb8484612c1b565b806001600160a01b031663522f681585856040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561282257600080fd5b505af1158015612836573d6000803e3d6000fd5b50505050505050505050565b3390565b6040805160609390931b6bffffffffffffffffffffffff19166020808501919091526034808501939093528151808503909301835260549093019052805191012090565b6001600160a01b0383166128d1576040805162461bcd60e51b81526020600482015260096024820152684248503a452d34303360b81b604482015290519081900360640190fd5b306001600160a01b0316826001600160a01b0316636352211e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561291f57600080fd5b505afa158015612933573d6000803e3d6000fd5b505050506040513d602081101561294957600080fd5b50516001600160a01b03161415612a0c57604080516323b872dd60e01b81523060048201526001600160a01b038581166024830152604482018490529151918416916323b872dd9160648082019260009290919082900301818387803b1580156129b257600080fd5b505af11580156129c6573d6000803e3d6000fd5b5050505080826001600160a01b0316846001600160a01b03167ffefe036cac4ee3a4aca074a81cbcc4376e1484693289078dbec149c890101d5b60405160405180910390a45b505050565b6001600160a01b038316612a58576040805162461bcd60e51b81526020600482015260096024820152684248503a452d34303360b81b604482015290519081900360640190fd5b80826001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612aa657600080fd5b505afa158015612aba573d6000803e3d6000fd5b505050506040513d6020811015612ad057600080fd5b505110612a0c57612aeb6001600160a01b0383168483612cbf565b816001600160a01b0316836001600160a01b03167f6c9d637297625e945b296ff73a71fcfbd0a9e062652b6491a921c4c60194176b836040518082815260200191505060405180910390a3505050565b6002546000908190612b55906001600160a01b0316612d11565b9050806001600160a01b031663c4d66de8600460019054906101000a90046001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b158015612bbb57600080fd5b505af1158015612bcf573d6000803e3d6000fd5b5092935050505090565b6000610b6683836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612d63565b6001600160a01b038216612c62576040805162461bcd60e51b81526020600482015260096024820152684248503a452d34303360b81b604482015290519081900360640190fd5b804710612cbb57612c7c6001600160a01b03831682612dfa565b6040805182815290516001600160a01b038416917eddb683bb45cd5d0ad8a200c6fae7152b1c236ee90a4a37db692407f5cc38bd919081900360200190a25b5050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612a0c908490612edf565b6000808260601b9050604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528160148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f0949350505050565b60008184841115612df25760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612db7578181015183820152602001612d9f565b50505050905090810190601f168015612de45780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b80471015612e4f576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114612e9a576040519150601f19603f3d011682016040523d82523d6000602084013e612e9f565b606091505b5050905080612a0c5760405162461bcd60e51b815260040180806020018281038252603a815260200180613167603a913960400191505060405180910390fd5b6060612f34826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612f909092919063ffffffff16565b805190915015612a0c57808060200190516020811015612f5357600080fd5b5051612a0c5760405162461bcd60e51b815260040180806020018281038252602a8152602001806131c1602a913960400191505060405180910390fd5b606061103a84846000856060612fa585613107565b612ff6576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106130355780518252601f199092019160209182019101613016565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613097576040519150601f19603f3d011682016040523d82523d6000602084013e61309c565b606091505b509150915081156130b057915061103a9050565b8051156130c05780518082602001fd5b60405162461bcd60e51b8152602060048201818152865160248401528651879391928392604401919085019080838360008315612db7578181015183820152602001612d9f565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061103a57505015159291505056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d617920686176652072657665727465644f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a2646970667358221220dcd2c60b9f4c78f70dd32de7092adf7002d027d54ca0a89205d3b94b6a4d034864736f6c634300060c0033608060405234801561001057600080fd5b50611f06806100206000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80637abdd2d1116100ad578063c4d66de811610071578063c4d66de814610503578063c87f3c0314610529578063ebb6dad814610531578063ff1f2b7514610557578063ff7885e8146105935761012c565b80637abdd2d114610314578063883c042b1461033a578063a0cc02e014610374578063a18ea08f146103b6578063b744a850146104e65761012c565b8063522f6815116100f4578063522f6815146102215780636edfab6b1461024d57806374ee6b621461027957806379ee54f7146102af5780637aaa3470146102d55761012c565b80630efe6a8b146101315780631071dd991461017557806334115f651461017d5780634025feb2146101b357806344004cc1146101eb575b600080fd5b6101636004803603606081101561014757600080fd5b506001600160a01b0381351690602081013590604001356105cb565b60408051918252519081900360200190f35b61016361062c565b6101636004803603606081101561019357600080fd5b506001600160a01b0381358116916020810135909116906040013561063d565b6101e9600480360360608110156101c957600080fd5b506001600160a01b03813581169160208101359091169060400135610694565b005b6101e96004803603606081101561020157600080fd5b506001600160a01b038135811691602081013590911690604001356106ef565b6101e96004803603604081101561023757600080fd5b506001600160a01b038135169060200135610745565b6101e96004803603604081101561026357600080fd5b506001600160a01b03813516906020013561079e565b6101636004803603606081101561028f57600080fd5b506001600160a01b0381358116916020810135909116906040013561080f565b610163600480360360208110156102c557600080fd5b50356001600160a01b0316610866565b6102fb600480360360208110156102eb57600080fd5b50356001600160a01b03166108e9565b6040805192835260208301919091528051918290030190f35b6101636004803603602081101561032a57600080fd5b50356001600160a01b03166108fe565b6103606004803603602081101561035057600080fd5b50356001600160a01b031661090f565b604080519115158252519081900360200190f35b61039a6004803603602081101561038a57600080fd5b50356001600160a01b0316610960565b604080516001600160a01b039092168252519081900360200190f35b610471600480360360608110156103cc57600080fd5b6001600160a01b03823516916020810135918101906060810160408201356401000000008111156103fc57600080fd5b82018360208201111561040e57600080fd5b8035906020019184600183028401116401000000008311171561043057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506109b1945050505050565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104ab578181015183820152602001610493565b50505050905090810190601f1680156104d85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61039a600480360360208110156104fc57600080fd5b5035610b3f565b6101e96004803603602081101561051957600080fd5b50356001600160a01b0316610b64565b6101e9610b8e565b6101636004803603602081101561054757600080fd5b50356001600160a01b0316610bec565b6102fb6004803603608081101561056d57600080fd5b506001600160a01b03813581169160208101358216916040820135169060600135610bf7565b6102fb600480360360608110156105a957600080fd5b506001600160a01b038135811691602081013582169160409091013516610c5e565b600080546001600160a01b03163314610617576040805162461bcd60e51b81526020600482015260096024820152685357423a452d31303960b81b604482015290519081900360640190fd5b610622848484610ceb565b90505b9392505050565b60006106386004610dda565b905090565b600080546001600160a01b03163314610689576040805162461bcd60e51b81526020600482015260096024820152685357423a452d31303960b81b604482015290519081900360640190fd5b610622848484610de5565b6000546001600160a01b031633146106df576040805162461bcd60e51b81526020600482015260096024820152685357423a452d31303960b81b604482015290519081900360640190fd5b6106ea838383610f34565b505050565b6000546001600160a01b0316331461073a576040805162461bcd60e51b81526020600482015260096024820152685357423a452d31303960b81b604482015290519081900360640190fd5b6106ea8383836110ba565b6000546001600160a01b03163314610790576040805162461bcd60e51b81526020600482015260096024820152685357423a452d31303960b81b604482015290519081900360640190fd5b61079a82826111e4565b5050565b6000546001600160a01b031633146107e9576040805162461bcd60e51b81526020600482015260096024820152685357423a452d31303960b81b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b039390931692909217909155600255565b600080546001600160a01b0316331461085b576040805162461bcd60e51b81526020600482015260096024820152685357423a452d31303960b81b604482015290519081900360640190fd5b610622848484611287565b6000816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156108b557600080fd5b505afa1580156108c9573d6000803e3d6000fd5b505050506040513d60208110156108df57600080fd5b505190505b919050565b6000806108f583611366565b91509150915091565b6000610909826113fc565b92915050565b6007546040805163883c042b60e01b81526001600160a01b0384811660048301529151600093929092169163883c042b91602480820192602092909190829003018186803b1580156108b557600080fd5b60075460408051630506601760e51b81526001600160a01b0384811660048301529151600093929092169163a0cc02e091602480820192602092909190829003018186803b1580156108b557600080fd5b6000546060906001600160a01b031633146109ff576040805162461bcd60e51b81526020600482015260096024820152685357423a452d31303960b81b604482015290519081900360640190fd5b60006060856001600160a01b031685856040518082805190602001908083835b60208310610a3e5780518252601f199092019160209182019101610a1f565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114610aa0576040519150601f19603f3d011682016040523d82523d6000602084013e610aa5565b606091505b5091509150818190610b355760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610afa578181015183820152602001610ae2565b50505050905090810190601f168015610b275780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5095945050505050565b6000610b4b6004610dda565b8210610b59575060006108e4565b610909600483611417565b610b6c610b8e565b600780546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031615610bd8576040805162461bcd60e51b815260206004820152600960248201526829aba11d229698181960b91b604482015290519081900360640190fd5b600080546001600160a01b03191633179055565b600061090982611423565b6000805481906001600160a01b03163314610c45576040805162461bcd60e51b81526020600482015260096024820152685357423a452d31303960b81b604482015290519081900360640190fd5b610c518686868661147a565b9150915094509492505050565b6000805481906001600160a01b03163314610cac576040805162461bcd60e51b81526020600482015260096024820152685357423a452d31303960b81b604482015290519081900360640190fd5b6000610cb7846113fc565b90506000610cc485611366565b9150610cdd9050878787610cd8868661176e565b61147a565b935093505050935093915050565b6000610cf6846117c8565b6001600160a01b038416600090815260066020526040902054610d19908461176e565b6001600160a01b03808616600090815260066020526040902091909155600754610d45911685856117e5565b60075460408051630efe6a8b60e01b81526001600160a01b038781166004830152602482018790526044820186905291516000939290921691630efe6a8b9160648082019260209290919082900301818787803b158015610da557600080fd5b505af1158015610db9573d6000803e3d6000fd5b505050506040513d6020811015610dcf57600080fd5b505195945050505050565b6000610909826117f9565b600080610df184611366565b50905080610e03576000915050610625565b80831115610e0f578092505b600354610e1c908461176e565b60035560075460408051630506601760e51b81526001600160a01b0387811660048301529151600093929092169163a0cc02e091602480820192602092909190829003018186803b158015610e7057600080fd5b505afa158015610e84573d6000803e3d6000fd5b505050506040513d6020811015610e9a57600080fd5b5051600754909150610eb6906001600160a01b031682866117e5565b60075460408051636ce5768960e11b81526001600160a01b0389811660048301528881166024830152604482018890529151919092169163d9caed1291606480830192600092919082900301818387803b158015610f1357600080fd5b505af1158015610f27573d6000803e3d6000fd5b5050505050509392505050565b6001600160a01b038316610f7b576040805162461bcd60e51b81526020600482015260096024820152684248503a452d34303360b81b604482015290519081900360640190fd5b306001600160a01b0316826001600160a01b0316636352211e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610fc957600080fd5b505afa158015610fdd573d6000803e3d6000fd5b505050506040513d6020811015610ff357600080fd5b50516001600160a01b031614156106ea57604080516323b872dd60e01b81523060048201526001600160a01b038581166024830152604482018490529151918416916323b872dd9160648082019260009290919082900301818387803b15801561105c57600080fd5b505af1158015611070573d6000803e3d6000fd5b5050505080826001600160a01b0316846001600160a01b03167ffefe036cac4ee3a4aca074a81cbcc4376e1484693289078dbec149c890101d5b60405160405180910390a4505050565b6001600160a01b038316611101576040805162461bcd60e51b81526020600482015260096024820152684248503a452d34303360b81b604482015290519081900360640190fd5b80826001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561114f57600080fd5b505afa158015611163573d6000803e3d6000fd5b505050506040513d602081101561117957600080fd5b5051106106ea576111946001600160a01b03831684836117fd565b816001600160a01b0316836001600160a01b03167f6c9d637297625e945b296ff73a71fcfbd0a9e062652b6491a921c4c60194176b836040518082815260200191505060405180910390a3505050565b6001600160a01b03821661122b576040805162461bcd60e51b81526020600482015260096024820152684248503a452d34303360b81b604482015290519081900360640190fd5b80471061079a576112456001600160a01b0383168261184f565b6040805182815290516001600160a01b038416917eddb683bb45cd5d0ad8a200c6fae7152b1c236ee90a4a37db692407f5cc38bd919081900360200190a25050565b604080516370a0823160e01b81523060048201819052915160009291859184916001600160a01b038416916370a0823191602480820192602092909190829003018186803b1580156112d857600080fd5b505afa1580156112ec573d6000803e3d6000fd5b505050506040513d602081101561130257600080fd5b5051905084811015611347576040805162461bcd60e51b81526020600482015260096024820152684153573a452d34313160b81b604482015290519081900360640190fd5b61135b6001600160a01b03831688876117fd565b509295945050505050565b600080600061137484611423565b90506000611381856113fc565b9050600061138f8383611934565b600254909150156113e85761271081116113ac57600094506113e8565b6113e56003546113df6127106113d96002546113d36003548861176e90919063ffffffff16565b90611976565b906119cf565b90611934565b94505b6113f28186611934565b9350505050915091565b6001600160a01b031660009081526006602052604090205490565b60006106258383611a11565b600754604080516351bd551f60e01b81523060048201526001600160a01b038481166024830152915160009392909216916351bd551f91604480820192602092909190829003018186803b1580156108b557600080fd5b6000806000611488856113fc565b905060008061149687611366565b915091508086101561153357811561152b5760006114c4826113d9896b033b2e3c9fd0803ce8000000611976565b90506114ef6b033b2e3c9fd0803ce80000006113d9836113d36003548861176e90919063ffffffff16565b95506003548611611513576003546115079087611934565b60035560009550611529565b600354611521908790611934565b600060035595505b505b8593506115aa565b600061153f8783611934565b905083811115611556576115538483611934565b90505b9194508491611565828261176e565b600060038190556001600160a01b038a1681526006602052604090205490955061158f9082611934565b6001600160a01b038916600090815260066020526040902055505b60075460408051630506601760e51b81526001600160a01b038a811660048301529151600093929092169163a0cc02e091602480820192602092909190829003018186803b1580156115fb57600080fd5b505afa15801561160f573d6000803e3d6000fd5b505050506040513d602081101561162557600080fd5b505160075490915061164a906001600160a01b031682611645888a61176e565b6117e5565b85156116ec5760006001600160a01b038a16611671576001546001600160a01b0316611673565b895b60075460408051636ce5768960e11b81526001600160a01b0380851660048301528d81166024830152604482018c9052915193945091169163d9caed129160648082019260009290919082900301818387803b1580156116d257600080fd5b505af11580156116e6573d6000803e3d6000fd5b50505050505b60075460408051636ce5768960e11b81526001600160a01b038d811660048301528b81166024830152604482018990529151919092169163d9caed1291606480830192600092919082900301818387803b15801561174957600080fd5b505af115801561175d573d6000803e3d6000fd5b505050505050505094509492505050565b600082820183811015610625576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6117d3600482611a75565b6117e25761079a600482611a8a565b50565b6106ea6001600160a01b03831684836117fd565b5490565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526106ea908490611a9f565b804710156118a4576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d80600081146118ef576040519150601f19603f3d011682016040523d82523d6000602084013e6118f4565b606091505b50509050806106ea5760405162461bcd60e51b815260040180806020018281038252603a815260200180611e4c603a913960400191505060405180910390fd5b600061062583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611b50565b60008261198557506000610909565b8282028284828161199257fe5b04146106255760405162461bcd60e51b8152600401808060200182810382526021815260200180611e866021913960400191505060405180910390fd5b600061062583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611baa565b81546000908210611a535760405162461bcd60e51b8152600401808060200182810382526022815260200180611e2a6022913960400191505060405180910390fd5b826000018281548110611a6257fe5b9060005260206000200154905092915050565b6000610625836001600160a01b038416611c0f565b6000610625836001600160a01b038416611c27565b6060611af4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611c719092919063ffffffff16565b8051909150156106ea57808060200190516020811015611b1357600080fd5b50516106ea5760405162461bcd60e51b815260040180806020018281038252602a815260200180611ea7602a913960400191505060405180910390fd5b60008184841115611ba25760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610afa578181015183820152602001610ae2565b505050900390565b60008183611bf95760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610afa578181015183820152602001610ae2565b506000838581611c0557fe5b0495945050505050565b60009081526001919091016020526040902054151590565b6000611c338383611c0f565b611c6957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610909565b506000610909565b606061062284846000856060611c8685611df0565b611cd7576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310611d165780518252601f199092019160209182019101611cf7565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611d78576040519150601f19603f3d011682016040523d82523d6000602084013e611d7d565b606091505b50915091508115611d91579150611de89050565b805115611da15780518082602001fd5b60405162461bcd60e51b8152602060048201818152865160248401528651879391928392604401919085019080838360008315610afa578181015183820152602001610ae2565b949350505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611de857505015159291505056fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e6473416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a264697066735822122082593b731983756adb051ebec3a491053d25344c3dbcbf51b8dde285e612661b64736f6c634300060c0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101c45760003560e01c806389a5799d116100f9578063c968b02711610097578063f2fde38b11610071578063f2fde38b146107fb578063f314a71e14610821578063fb3642d614610847578063fe34cc3f1461088d576101c4565b8063c968b02714610657578063db9f60ff14610798578063ed452778146107b7576101c4565b806392eefe9b116100d357806392eefe9b146105bd578063a9d16f3b146105e3578063b187bd2614610629578063b5795a9514610631576101c4565b806389a5799d146105315780638b8d9a161461057b5780638da5cb5b146105b5576101c4565b80633d76f93e11610166578063512adb1311610140578063512adb131461043c578063711ad4ec1461048b578063715018a6146104f3578063897f4ecb146104fb576101c4565b80633d76f93e146103585780634737c0c31461039c5780634ff83618146103f2576101c4565b8063238f1b98116101a2578063238f1b981461028557806328644061146102cf5780632be89305146102ec5780632da9ef8114610322576101c4565b806307009629146101c9578063157c5a42146101f9578063235dd2001461023d575b600080fd5b6101f7600480360360408110156101df57600080fd5b506001600160a01b03813516906020013515156108c7565b005b6101f7600480360360a081101561020f57600080fd5b506001600160a01b03813581169160208101359160408201358116916060810135909116906080013561097f565b6102736004803603606081101561025357600080fd5b506001600160a01b03813581169160208101359160409091013516610a9b565b60408051918252519081900360200190f35b6102bb6004803603606081101561029b57600080fd5b506001600160a01b03813581169160208101359160409091013516610b6d565b604080519115158252519081900360200190f35b6101f7600480360360208110156102e557600080fd5b5035610c19565b6102736004803603606081101561030257600080fd5b506001600160a01b03813581169160208101359160409091013516610c76565b6102736004803603606081101561033857600080fd5b506001600160a01b03813581169160208101359160409091013516610d11565b6101f7600480360360a081101561036e57600080fd5b506001600160a01b038135811691602081013591604082013581169160608101359091169060800135610dac565b6103d6600480360360808110156103b257600080fd5b506001600160a01b0381358116916020810135916040820135169060600135610ea7565b604080516001600160a01b039092168252519081900360200190f35b610273600480360360c081101561040857600080fd5b506001600160a01b038135811691602081013582169160408201359160608101358216916080820135169060a00135611042565b6104726004803603606081101561045257600080fd5b506001600160a01b038135811691602081013591604090910135166112b9565b6040805192835260208301919091528051918290030190f35b6104d5600480360360c08110156104a157600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013582169160808201359160a0013516611391565b60408051938452602084019290925282820152519081900360600190f35b6101f76115f2565b6103d66004803603606081101561051157600080fd5b506001600160a01b03813581169160208101359160409091013516611694565b610472600480360360c081101561054757600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013582169160808201359160a001351661172c565b6102736004803603608081101561059157600080fd5b506001600160a01b03813581169160208101359160408201351690606001356119a9565b6103d6611aff565b6101f7600480360360208110156105d357600080fd5b50356001600160a01b0316611b0e565b6104d5600480360360a08110156105f957600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013582169160809091013516611bb0565b6102bb611dea565b6101f76004803603602081101561064757600080fd5b50356001600160a01b0316611df3565b610723600480360360a081101561066d57600080fd5b6001600160a01b0382358116926020810135926040820135909216916060820135919081019060a0810160808201356401000000008111156106ae57600080fd5b8201836020820111156106c057600080fd5b803590602001918460018302840111640100000000831117156106e257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611ee4945050505050565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561075d578181015183820152602001610745565b50505050905090810190601f16801561078a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101f7600480360360208110156107ae57600080fd5b5035151561211b565b610273600480360360a08110156107cd57600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013590911690608001356121ba565b6101f76004803603602081101561081157600080fd5b50356001600160a01b03166123be565b6102bb6004803603602081101561083757600080fd5b50356001600160a01b03166124b6565b610472600480360360a081101561085d57600080fd5b506001600160a01b03813581169160208101358216916040820135916060810135821691608090910135166124cb565b6101f7600480360360808110156108a357600080fd5b506001600160a01b0381358116916020810135916040820135169060600135612739565b6108cf612842565b6000546001600160a01b0390811691161461091f576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b6001600160a01b038216600081815260066020908152604091829020805460ff1916851515908117909155825190815291517f47b3f841cfb31c3cdf247b5ec0118d0ded80f2b51a7c7da0b6da26549e49bd4c9281900390910190a25050565b610987612842565b6000546001600160a01b039081169116146109d7576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b60006109ec6001600160a01b03871686612846565b6000818152600360205260409020549091506001600160a01b0316610a1285858561288a565b806001600160a01b0316634025feb28686866040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b5050505050505050505050565b600080610ab16001600160a01b03861685612846565b6000818152600360205260409020549091506001600160a01b0316610ada576000915050610b66565b60008181526003602090815260408083205481516379ee54f760e01b81526001600160a01b038881166004830152925192909116936379ee54f79360248084019491939192918390030190829087803b158015610b3657600080fd5b505af1158015610b4a573d6000803e3d6000fd5b505050506040513d6020811015610b6057600080fd5b50519150505b9392505050565b600080610b836001600160a01b03861685612846565b6000818152600360205260409020549091506001600160a01b0316610bac576000915050610b66565b60008181526003602090815260409182902054825163883c042b60e01b81526001600160a01b0387811660048301529351939091169263883c042b92602480840193919291829003018186803b158015610c0557600080fd5b505afa158015610b4a573d6000803e3d6000fd5b610c21612842565b6000546001600160a01b03908116911614610c71576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b600555565b600080610c8c6001600160a01b03861685612846565b6000818152600360205260409020549091506001600160a01b0316610cb5576000915050610b66565b6000818152600360209081526040808320548151631d76db5b60e31b81526001600160a01b0388811660048301529251929091169363ebb6dad89360248084019491939192918390030190829087803b158015610b3657600080fd5b600080610d276001600160a01b03861685612846565b6000818152600360205260409020549091506001600160a01b0316610d50576000915050610b66565b6000818152600360209081526040808320548151637abdd2d160e01b81526001600160a01b03888116600483015292519290911693637abdd2d19360248084019491939192918390030190829087803b158015610b3657600080fd5b610db4612842565b6000546001600160a01b03908116911614610e04576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b6000610e196001600160a01b03871686612846565b6000818152600360205260409020549091506001600160a01b0316610e3f858585612a11565b806001600160a01b03166344004cc18686866040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015610a7a57600080fd5b6001546000906001600160a01b03163314610ef5576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b6000610f0a6001600160a01b03871686612846565b6000818152600360205260409020549091506001600160a01b03168061103657610f32612b3b565b600083815260036020526040902080546001600160a01b0319166001600160a01b0383811691909117909155909150851615610fd857806001600160a01b0316636edfab6b86866040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015610fbf57600080fd5b505af1158015610fd3573d6000803e3d6000fd5b505050505b806001600160a01b031686886001600160a01b03167f1cda30153ed04b1a2d5be381fcc3b30f512c22c6f3cbd755b87ad945660a2708888860405180836001600160a01b031681526020018281526020019250505060405180910390a45b9150505b949350505050565b6001546000906001600160a01b03163314611090576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b60006110a56001600160a01b03881687612846565b6000818152600360205260409020549091506001600160a01b0316806110fe576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34303360b81b604482015290519081900360640190fd5b6000816001600160a01b0316637aaa3470876040518263ffffffff1660e01b815260040180826001600160a01b031681526020019150506040805180830381600087803b15801561114e57600080fd5b505af1158015611162573d6000803e3d6000fd5b505050506040513d604081101561117857600080fd5b50519050841580159061118b5750848110155b6111c8576040805162461bcd60e51b815260206004820152600960248201526820aba69d22969a189960b91b604482015290519081900360640190fd5b816001600160a01b03166334115f658b88886040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050602060405180830381600087803b15801561123057600080fd5b505af1158015611244573d6000803e3d6000fd5b505050506040513d602081101561125a57600080fd5b5051604080516001600160a01b038a81168252602082018490528251939750808a16938c93918e16927fc5ee6437398fe6176ea602fb23e08746debd66700cd17f44b17b9214e4778a0a92908290030190a45050509695505050505050565b600080806112d06001600160a01b03871686612846565b6000818152600360205260409020549091506001600160a01b031615611387576000818152600360205260408082205481516307aaa34760e41b81526001600160a01b0388811660048301528351921693637aaa34709360248084019491939192918390030190829087803b15801561134857600080fd5b505af115801561135c573d6000803e3d6000fd5b505050506040513d604081101561137257600080fd5b50805160209091015190935091506113899050565b505b935093915050565b600154600090819081906001600160a01b031633146113e3576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b60006113f86001600160a01b038a1689612846565b6000818152600360205260409020549091506001600160a01b031680611451576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34303360b81b604482015290519081900360640190fd5b6000816001600160a01b0316637aaa34708a6040518263ffffffff1660e01b815260040180826001600160a01b031681526020019150506040805180830381600087803b1580156114a157600080fd5b505af11580156114b5573d6000803e3d6000fd5b505050506040513d60408110156114cb57600080fd5b506020015190508781106114e05760006114ea565b6114ea8882612bd9565b60408051600162e0d48b60e01b031981526001600160a01b038f811660048301528a811660248301528c81166044830152606482018c9052825193995085169263ff1f2b75926084808401939192918290030181600087803b15801561154f57600080fd5b505af1158015611563573d6000803e3d6000fd5b505050506040513d604081101561157957600080fd5b508051602091820151604080516001600160a01b038e811682529481018b9052808201849052606081018390529051929850909650828f16928d92908f16917f9cddee57762ce56bd97afc79f9c6bcd7946b3fe3b43b58b4f944e3190111f423919081900360800190a450505096509650969350505050565b6115fa612842565b6000546001600160a01b0390811691161461164a576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000806116aa6001600160a01b03861685612846565b6000818152600360205260409020549091506001600160a01b03166116d3576000915050610b66565b600081815260036020908152604091829020548251630506601760e51b81526001600160a01b0387811660048301529351939091169263a0cc02e092602480840193919291829003018186803b158015610c0557600080fd5b60015460009081906001600160a01b0316331461177c576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b60006117916001600160a01b03891688612846565b6000818152600360205260409020549091506001600160a01b0316806117ea576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34303360b81b604482015290519081900360640190fd5b6000816001600160a01b0316637aaa3470896040518263ffffffff1660e01b815260040180826001600160a01b031681526020019150506040805180830381600087803b15801561183a57600080fd5b505af115801561184e573d6000803e3d6000fd5b505050506040513d604081101561186457600080fd5b50602001519050861580159061187a5750868110155b6118b7576040805162461bcd60e51b815260206004820152600960248201526820aba69d22969a189960b91b604482015290519081900360640190fd5b60408051600162e0d48b60e01b031981526001600160a01b038d8116600483015288811660248301528a81166044830152606482018a905282519085169263ff1f2b7592608480820193918290030181600087803b15801561191857600080fd5b505af115801561192c573d6000803e3d6000fd5b505050506040513d604081101561194257600080fd5b5080516020918201516040805183815293840182905280519298509096506001600160a01b03808c16938d93918f16927f8c5afa972f06d20ce921881649de0917319195e46b7905b5c3bfeb2ebe62e8bd92918290030190a4505050965096945050505050565b6001546000906001600160a01b031633146119f7576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b6000611a0c6001600160a01b03871686612846565b6000818152600360209081526040808320546005548251630efe6a8b60e01b81526001600160a01b038b81166004830152602482018b90526044820192909252925195965016938493630efe6a8b93606480850194919392918390030190829087803b158015611a7b57600080fd5b505af1158015611a8f573d6000803e3d6000fd5b505050506040513d6020811015611aa557600080fd5b5051604080518681526020810183905281519295506001600160a01b03808916938a93918c16927f888889d6224fdc21d2a6f20b0f8a25cc561b82d8f051c7b471e65903d4d1654d92908290030190a45050949350505050565b6000546001600160a01b031690565b611b16612842565b6000546001600160a01b03908116911614611b66576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517f79f74fd5964b6943d8a1865abfb7f668c92fa3f32c0a2e3195da7d0946703ad790600090a250565b600154600090819081906001600160a01b03163314611c02576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b6000611c176001600160a01b03891688612846565b6000818152600360205260409020549091506001600160a01b031680611c70576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34303360b81b604482015290519081900360640190fd5b806001600160a01b0316637abdd2d1886040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050602060405180830381600087803b158015611cbf57600080fd5b505af1158015611cd3573d6000803e3d6000fd5b505050506040513d6020811015611ce957600080fd5b50516040805160016210ef4360e31b031981526001600160a01b038d8116600483015289811660248301528a81166044830152825193985084169263ff7885e8926064808401939192918290030181600087803b158015611d4957600080fd5b505af1158015611d5d573d6000803e3d6000fd5b505050506040513d6040811015611d7357600080fd5b508051602091820151604080516001600160a01b038c811682529481018a9052808201849052606081018390529051929750909550828d16928b92908d16917f9cddee57762ce56bd97afc79f9c6bcd7946b3fe3b43b58b4f944e3190111f423919081900360800190a45050955095509592505050565b60045460ff1690565b611dfb612842565b6000546001600160a01b03908116911614611e4b576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b6001600160a01b038116611e92576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34303360b81b604482015290519081900360640190fd5b60048054610100600160a81b0319166101006001600160a01b038416908102919091179091556040517f7c96177d7f838426dc6b53224d68914e2500c7f8ef49481c7ccc1d18157a35c090600090a250565b6001546060906001600160a01b03163314611f32576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b6000611f476001600160a01b03881687612846565b600081815260036020908152604080832054905163a18ea08f60e01b81526001600160a01b038a811660048301908152602483018b90526060604484019081528a5160648501528a519798509190931695869563a18ea08f958d958d958d9591949193608490910192860191908190849084905b83811015611fd3578181015183820152602001611fbb565b50505050905090810190601f1680156120005780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561202157600080fd5b505af1158015612035573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561205e57600080fd5b810190808051604051939291908464010000000082111561207e57600080fd5b90830190602082018581111561209357600080fd5b82516401000000008111828201881017156120ad57600080fd5b82525081516020918201929091019080838360005b838110156120da5781810151838201526020016120c2565b50505050905090810190601f1680156121075780820380516001836020036101000a031916815260200191505b506040525050509250505095945050505050565b612123612842565b6000546001600160a01b03908116911614612173576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b6004805482151560ff19909116811790915560408051918252517fa9bfed3d98385b3777389e321dbde773cf7d335fa604fefbae3dca93564f55869181900360200190a150565b6001546000906001600160a01b03163314612208576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b600061221d6001600160a01b03871686612846565b6000818152600360205260409020549091506001600160a01b031680612276576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34303360b81b604482015290519081900360640190fd5b6001600160a01b03851660009081526006602052604090205460ff166122cf576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34323360b81b604482015290519081900360640190fd5b806001600160a01b03166374ee6b628987876040518463ffffffff1660e01b815260040180846001600160a01b03168152602001836001600160a01b031681526020018281526020019350505050602060405180830381600087803b15801561233757600080fd5b505af115801561234b573d6000803e3d6000fd5b505050506040513d602081101561236157600080fd5b5051604080516001600160a01b038881168252602082018490528251939650808c16938a93918c16927f06f54f96ef088b89e726f3399f067502f7f3ab4864f09ba0fd5448eb9d450d3b92908290030190a4505095945050505050565b6123c6612842565b6000546001600160a01b03908116911614612416576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b6001600160a01b03811661245b5760405162461bcd60e51b81526004018080602001828103825260268152602001806131416026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60066020526000908152604090205460ff1681565b60015460009081906001600160a01b0316331461251b576040805162461bcd60e51b81526020600482015260096024820152680ae9a84748a5a6260760bb1b604482015290519081900360640190fd5b60006125306001600160a01b03881687612846565b6000818152600360205260409020549091506001600160a01b031680612589576040805162461bcd60e51b815260206004820152600960248201526841574d3a452d34303360b81b604482015290519081900360640190fd5b6000816001600160a01b0316637aaa3470886040518263ffffffff1660e01b815260040180826001600160a01b031681526020019150506040805180830381600087803b1580156125d957600080fd5b505af11580156125ed573d6000803e3d6000fd5b505050506040513d604081101561260357600080fd5b5060200151905080612648576040805162461bcd60e51b815260206004820152600960248201526820aba69d22969a189960b91b604482015290519081900360640190fd5b60408051600162e0d48b60e01b031981526001600160a01b038c81166004830152888116602483015289811660448301526064820184905282519085169263ff1f2b7592608480820193918290030181600087803b1580156126a957600080fd5b505af11580156126bd573d6000803e3d6000fd5b505050506040513d60408110156126d357600080fd5b5080516020918201516040805183815293840182905280519298509096506001600160a01b03808b16938c93918e16927f8c5afa972f06d20ce921881649de0917319195e46b7905b5c3bfeb2ebe62e8bd92918290030190a45050509550959350505050565b612741612842565b6000546001600160a01b03908116911614612791576040805162461bcd60e51b815260206004820181905260248201526000805160206131a1833981519152604482015290519081900360640190fd5b60006127a66001600160a01b03861685612846565b6000818152600360205260409020549091506001600160a01b03166127cb8484612c1b565b806001600160a01b031663522f681585856040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561282257600080fd5b505af1158015612836573d6000803e3d6000fd5b50505050505050505050565b3390565b6040805160609390931b6bffffffffffffffffffffffff19166020808501919091526034808501939093528151808503909301835260549093019052805191012090565b6001600160a01b0383166128d1576040805162461bcd60e51b81526020600482015260096024820152684248503a452d34303360b81b604482015290519081900360640190fd5b306001600160a01b0316826001600160a01b0316636352211e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561291f57600080fd5b505afa158015612933573d6000803e3d6000fd5b505050506040513d602081101561294957600080fd5b50516001600160a01b03161415612a0c57604080516323b872dd60e01b81523060048201526001600160a01b038581166024830152604482018490529151918416916323b872dd9160648082019260009290919082900301818387803b1580156129b257600080fd5b505af11580156129c6573d6000803e3d6000fd5b5050505080826001600160a01b0316846001600160a01b03167ffefe036cac4ee3a4aca074a81cbcc4376e1484693289078dbec149c890101d5b60405160405180910390a45b505050565b6001600160a01b038316612a58576040805162461bcd60e51b81526020600482015260096024820152684248503a452d34303360b81b604482015290519081900360640190fd5b80826001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612aa657600080fd5b505afa158015612aba573d6000803e3d6000fd5b505050506040513d6020811015612ad057600080fd5b505110612a0c57612aeb6001600160a01b0383168483612cbf565b816001600160a01b0316836001600160a01b03167f6c9d637297625e945b296ff73a71fcfbd0a9e062652b6491a921c4c60194176b836040518082815260200191505060405180910390a3505050565b6002546000908190612b55906001600160a01b0316612d11565b9050806001600160a01b031663c4d66de8600460019054906101000a90046001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b158015612bbb57600080fd5b505af1158015612bcf573d6000803e3d6000fd5b5092935050505090565b6000610b6683836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612d63565b6001600160a01b038216612c62576040805162461bcd60e51b81526020600482015260096024820152684248503a452d34303360b81b604482015290519081900360640190fd5b804710612cbb57612c7c6001600160a01b03831682612dfa565b6040805182815290516001600160a01b038416917eddb683bb45cd5d0ad8a200c6fae7152b1c236ee90a4a37db692407f5cc38bd919081900360200190a25b5050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612a0c908490612edf565b6000808260601b9050604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528160148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f0949350505050565b60008184841115612df25760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612db7578181015183820152602001612d9f565b50505050905090810190601f168015612de45780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b80471015612e4f576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114612e9a576040519150601f19603f3d011682016040523d82523d6000602084013e612e9f565b606091505b5050905080612a0c5760405162461bcd60e51b815260040180806020018281038252603a815260200180613167603a913960400191505060405180910390fd5b6060612f34826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612f909092919063ffffffff16565b805190915015612a0c57808060200190516020811015612f5357600080fd5b5051612a0c5760405162461bcd60e51b815260040180806020018281038252602a8152602001806131c1602a913960400191505060405180910390fd5b606061103a84846000856060612fa585613107565b612ff6576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106130355780518252601f199092019160209182019101613016565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613097576040519150601f19603f3d011682016040523d82523d6000602084013e61309c565b606091505b509150915081156130b057915061103a9050565b8051156130c05780518082602001fd5b60405162461bcd60e51b8152602060048201818152865160248401528651879391928392604401919085019080838360008315612db7578181015183820152602001612d9f565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061103a57505015159291505056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d617920686176652072657665727465644f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a2646970667358221220dcd2c60b9f4c78f70dd32de7092adf7002d027d54ca0a89205d3b94b6a4d034864736f6c634300060c0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.