15M+ users trust MoonPay. Checkout with your preferred payment method.
Ready to onboard to Ethereum? With MetaMask Portfolio, you're in control.
Get up to 0.5% cashback per purchase and receive daily interest.
Ready to simplify your web3 experience? Try the all-in-one web3 app trusted by millions worldwide.
Opt-in, make your first trade on Exchange Plus & receive random crypto rewards from 10,000 SHIB, to 0.01 BTC.
Everyday giveaways up to 100 ETH, Lucky Spins. Deposit BONUS 300% and Cashbacks!
9 years old Licensed Crypto Casino, Instant Withdraw 24/7, 6000+ Slots available, Paypal Deposit, Instant Live Support 24/7, 30% Rakeback.
5000+ Slots & Live Casino Games, 50+cryptos. Register with Etherscan and get 760% deposit bonus. Win Big$, withdraw it fast.
5000+ Slots & Live Casino Games, 50+cryptos. Register with Etherscan and get 760% deposit bonus. Win Big$, withdraw it fast.
Play 100s of games anonymously with all major cryptos. Join CryptoWins & start winning!
Anonymous play on awesome games - sign up now for 25 free jackpot spins - worth $100s!
Overview
ETH Balance
Eth Value
$0.82 (@ $3,267.43/ETH)Token Holdings
Could not find any matches!
- ERC-20 Tokens (36)4.98954081 CHEXChintai Exch... (CHEX)$0.61@0.12310.02539042 VECVector (VEC)$0.10@4.009.85979996 CRVCurve DAO To... (CRV)$2.61@0.2649136.33336089 crvUSDCurve.Fi USD... (crvUSD)$135.68@0.99524.99558241 FRAXFrax (FRAX)$4.98@0.99730.00697573 MetisMetis Token (Metis)$0.34@49.100.00171947 rETHRocket Pool ... (rETH)$6.30@3,665.650.00049342 rsETHrsETH (rsETH)$1.64@3,329.2958.16811746 sUSDeStaked USDe (sUSDe)$58.15@0.999639.99213031 USDeUSDe (USDe)$39.98@0.99962.0984593 LINKChainLink To... (LINK)$28.50@13.580.00000117 DAIDai Stableco... (DAI)$0.00@0.99960.18938731 SAFESafe Token (SAFE)$0.21@1.120 stETHstETH (stETH)$0.00@3,270.78200.457791 USDTTether USD (USDT)$200.46@1.00369.886193 USDCUSDC (USDC)$369.89@1.000.00001741 WBTCWrapped BTC (WBTC)$1.20@68,675.000.00833 WETHWrapped Ethe... (WETH)$27.23@3,268.94731,994.65132072 ANDYAndy$0.28@0.00010.37239776 DSyncDestra Network$0.09@0.2301799.23068455 KARATEKarate$0.71@0.00090.12297793 MPLMaple Token$2.44@19.872.48371488 MATICMatic Token$1.28@0.51729,248,976.83293861 MogMog Coin$15.06@0.000 USDMMountain Protocol USD$0.00@1.003421,489.91749664 TITANXTITAN X$0.11@0.0069.98940065 TOKENTokenFi$4.93@0.07050.00099915 vETHVector ETH$3.21@3,217.643.53010688 yPRISMAYearn PRISMA19.98620506 cvxCRVConvex CRV$5.32@0.26645,467.87169109 HOPPYHoppy$0.52@0.000119.9961468 LUSDLUSD Stablecoin$19.97@0.99859,996,297.66007748 PEIPEIPeiPei$2.94@0.009,993,780.06115502 PORKPepeFork$0.85@0.001 TokenERC-20 TOKEN*[Suspicious]9,000 TokenERC-20 TOKEN*[Suspicious]NFT Tokens (7)
More Info
Private Name Tags
ContractCreator
- Transactions
- Internal Transactions
- Token Transfers (ERC-20)
- NFT Transfers
- Contract
- Events
- Analytics
- Multichain Portfolio
- Filter by Tx Type:
- Tx
- Internal Tx
- ERC-20
- NFTs
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||||
---|---|---|---|---|---|---|---|---|
20390774 | 2024-07-26 12:38:11 | 29 hrs ago | 1721997491 | 4.72835637 ETH$15,449.59 | ||||
20390774 | 2024-07-26 12:38:11 | 29 hrs ago | 1721997491 | 4.72835637 ETH$15,449.59 | ||||
20361781 | 2024-07-22 11:29:47 | 5 days ago | 1721647787 | 3.50760756 ETH$11,460.87 | ||||
20361781 | 2024-07-22 11:29:47 | 5 days ago | 1721647787 | 3.50760756 ETH$11,460.87 | ||||
20361288 | 2024-07-22 9:50:59 | 5 days ago | 1721641859 | 4.01807057 ETH$13,128.77 | ||||
20361288 | 2024-07-22 9:50:59 | 5 days ago | 1721641859 | 4.01807057 ETH$13,128.77 | ||||
20360698 | 2024-07-22 7:52:11 | 5 days ago | 1721634731 | 1.18084056 ETH$3,858.32 | ||||
20360698 | 2024-07-22 7:52:11 | 5 days ago | 1721634731 | 1.18084056 ETH$3,858.32 | ||||
20360458 | 2024-07-22 7:03:47 | 5 days ago | 1721631827 | 1.1474546 ETH$3,749.23 | ||||
20360458 | 2024-07-22 7:03:47 | 5 days ago | 1721631827 | 1.1474546 ETH$3,749.23 | ||||
20360423 | 2024-07-22 6:56:47 | 5 days ago | 1721631407 | 1.14818512 ETH$3,751.62 | ||||
20360423 | 2024-07-22 6:56:47 | 5 days ago | 1721631407 | 1.14818512 ETH$3,751.62 | ||||
20357156 | 2024-07-21 19:59:11 | 5 days ago | 1721591951 | 1.12494217 ETH$3,675.67 | ||||
20357156 | 2024-07-21 19:59:11 | 5 days ago | 1721591951 | 1.12494217 ETH$3,675.67 | ||||
20335232 | 2024-07-18 18:35:11 | 9 days ago | 1721327711 | 104.99391916 ETH$343,060.54 | ||||
20335232 | 2024-07-18 18:35:11 | 9 days ago | 1721327711 | 104.99391916 ETH$343,060.54 | ||||
20290794 | 2024-07-12 13:43:23 | 15 days ago | 1720791803 | 0.98416767 ETH$3,215.70 | ||||
20290794 | 2024-07-12 13:43:23 | 15 days ago | 1720791803 | 0.85182387 ETH$2,783.28 | ||||
20290794 | 2024-07-12 13:43:23 | 15 days ago | 1720791803 | 0.03308604 ETH$108.11 | ||||
20290794 | 2024-07-12 13:43:23 | 15 days ago | 1720791803 | 0.03308087 ETH$108.09 | ||||
20290794 | 2024-07-12 13:43:23 | 15 days ago | 1720791803 | 0.03308827 ETH$108.11 | ||||
20290794 | 2024-07-12 13:43:23 | 15 days ago | 1720791803 | 0.0330886 ETH$108.11 | ||||
20290792 | 2024-07-12 13:42:59 | 15 days ago | 1720791779 | 0.71893244 ETH$2,349.06 | ||||
20290792 | 2024-07-12 13:42:59 | 15 days ago | 1720791779 | 0.71893244 ETH$2,349.06 | ||||
20264664 | 2024-07-08 22:08:47 | 18 days ago | 1720476527 | 82.72025345 ETH$270,282.84 |
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.17; import {VM} from "enso-weiroll/VM.sol"; import {MinimalWallet} from "shortcuts-contracts/wallet/MinimalWallet.sol"; import {AccessController} from "shortcuts-contracts/access/AccessController.sol"; contract SolverEnsoShortcuts is VM, MinimalWallet, AccessController { address private constant settlement = 0x9008D19f58AAbD9eD0D60971565AA8510560ab41; constructor(address owner) { _setPermission(OWNER_ROLE, owner, true); } // @notice Execute a shortcut from a solver // @param commands An array of bytes32 values that encode calls // @param state An array of bytes that are used to generate call data for each command function executeShortcut(bytes32[] calldata commands, bytes[] calldata state) external payable returns (bytes[] memory) { // we could use the AccessController here to check if the msg.sender is the settlement address // but as it's a hot path we do a less gas intensive check if (msg.sender != settlement) revert NotPermitted(); return _execute(commands, state); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.16; import "./CommandBuilder.sol"; abstract contract VM { using CommandBuilder for bytes[]; uint256 constant FLAG_CT_DELEGATECALL = 0x00; // Delegate call not currently supported uint256 constant FLAG_CT_CALL = 0x01; uint256 constant FLAG_CT_STATICCALL = 0x02; uint256 constant FLAG_CT_VALUECALL = 0x03; uint256 constant FLAG_CT_MASK = 0x03; uint256 constant FLAG_DATA = 0x20; uint256 constant FLAG_EXTENDED_COMMAND = 0x40; uint256 constant FLAG_TUPLE_RETURN = 0x80; uint256 constant SHORT_COMMAND_FILL = 0x000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; error ExecutionFailed( uint256 command_index, address target, string message ); function _execute(bytes32[] calldata commands, bytes[] memory state) internal returns (bytes[] memory) { bytes32 command; uint256 flags; bytes32 indices; bool success; bytes memory outData; uint256 commandsLength = commands.length; uint256 indicesLength; for (uint256 i; i < commandsLength; i = _uncheckedIncrement(i)) { command = commands[i]; flags = uint256(uint8(bytes1(command << 32))); if (flags & FLAG_EXTENDED_COMMAND != 0) { i = _uncheckedIncrement(i); indices = commands[i]; indicesLength = 32; } else { indices = bytes32(uint256(command << 40) | SHORT_COMMAND_FILL); indicesLength = 6; } if (flags & FLAG_CT_MASK == FLAG_CT_CALL) { (success, outData) = address(uint160(uint256(command))).call( // target // inputs flags & FLAG_DATA == 0 ? state.buildInputs( bytes4(command), // selector indices, indicesLength ) : state[ uint8(bytes1(indices)) & CommandBuilder.IDX_VALUE_MASK ] ); } else if (flags & FLAG_CT_MASK == FLAG_CT_STATICCALL) { (success, outData) = address(uint160(uint256(command))) // target .staticcall( // inputs flags & FLAG_DATA == 0 ? state.buildInputs( bytes4(command), // selector indices, indicesLength ) : state[ uint8(bytes1(indices)) & CommandBuilder.IDX_VALUE_MASK ] ); } else if (flags & FLAG_CT_MASK == FLAG_CT_VALUECALL) { bytes memory v = state[ uint8(bytes1(indices)) & CommandBuilder.IDX_VALUE_MASK ]; require(v.length == 32, "Value must be 32 bytes"); uint256 callEth = uint256(bytes32(v)); (success, outData) = address(uint160(uint256(command))).call{ // target value: callEth }( // inputs flags & FLAG_DATA == 0 ? state.buildInputs( bytes4(command), // selector indices << 8, // skip value input indicesLength - 1 // max indices length reduced by value input ) : state[ uint8(bytes1(indices << 8)) & // first byte after value input CommandBuilder.IDX_VALUE_MASK ] ); } else { revert("Invalid calltype"); } if (!success) { string memory message = "Unknown"; if (outData.length > 68) { // This might be an error message, parse the outData // Estimate the bytes length of the possible error message uint256 estimatedLength = _estimateBytesLength(outData, 68); // Remove selector. First 32 bytes should be a pointer that indicates the start of data in memory assembly { outData := add(outData, 4) } uint256 pointer = uint256(bytes32(outData)); if (pointer == 32) { // Remove pointer. If it is a string, the next 32 bytes will hold the size assembly { outData := add(outData, 32) } uint256 size = uint256(bytes32(outData)); // If the size variable is the same as the estimated bytes length, we can be fairly certain // this is a dynamic string, so convert the bytes to a string and emit the message. While an // error function with 3 static parameters is capable of producing a similar output, there is // low risk of a contract unintentionally emitting a message. if (size == estimatedLength) { // Remove size. The remaining data should be the string content assembly { outData := add(outData, 32) } message = string(outData); } } } revert ExecutionFailed({ command_index: flags & FLAG_EXTENDED_COMMAND == 0 ? i : i - 1, target: address(uint160(uint256(command))), message: message }); } if (flags & FLAG_TUPLE_RETURN != 0) { state.writeTuple(bytes1(command << 88), outData); } else { state = state.writeOutputs(bytes1(command << 88), outData); } } return state; } function _estimateBytesLength(bytes memory data, uint256 pos) internal pure returns (uint256 estimate) { uint256 length = data.length; estimate = length - pos; // Assume length equals alloted space for (uint256 i = pos; i < length; ) { if (data[i] == 0) { // Zero bytes found, adjust estimated length estimate = i - pos; break; } unchecked { ++i; } } } function _uncheckedIncrement(uint256 i) private pure returns (uint256) { unchecked { ++i; } return i; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.16; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; import "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; import "../access/ACL.sol"; import "../access/Roles.sol"; contract MinimalWallet is ACL, Roles, ERC721Holder, ERC1155Holder { using SafeERC20 for IERC20; enum Protocol { ETH, ERC20, ERC721, ERC1155 } struct TransferNote { Protocol protocol; address token; uint256[] ids; uint256[] amounts; } struct ApprovalNote { Protocol protocol; address token; address[] operators; } error WithdrawFailed(); error InvalidArrayLength(); //////////////////////////////////////////////////// // External functions ////////////////////////////// //////////////////////////////////////////////////// // @notice Withdraw an array of assets // @dev Works for ETH, ERC20s, ERC721s, and ERC1155s // @param notes A tuple that contains the protocol id, token address, array of ids and amounts function withdraw(TransferNote[] calldata notes) external isPermitted(OWNER_ROLE) { TransferNote memory note; Protocol protocol; uint256[] memory ids; uint256[] memory amounts; uint256 length = notes.length; for (uint256 i; i < length; ) { note = notes[i]; protocol = note.protocol; if (protocol == Protocol.ETH) { amounts = note.amounts; if (amounts.length != 1) revert InvalidArrayLength(); _withdrawETH(amounts[0]); } else if (protocol == Protocol.ERC20) { amounts = note.amounts; if (amounts.length != 1) revert InvalidArrayLength(); _withdrawERC20(IERC20(note.token), amounts[0]); } else if (protocol == Protocol.ERC721) { ids = note.ids; _withdrawERC721s(IERC721(note.token), ids); } else if (protocol == Protocol.ERC1155) { ids = note.ids; amounts = note.amounts; _withdrawERC1155s(IERC1155(note.token), ids, amounts); } unchecked { ++i; } } } // @notice Withdraw ETH from this contract to the msg.sender // @param amount The amount of ETH to be withdrawn function withdrawETH(uint256 amount) external isPermitted(OWNER_ROLE) { _withdrawETH(amount); } // @notice Withdraw ERC20s // @param erc20s An array of erc20 addresses // @param amounts An array of amounts for each erc20 function withdrawERC20s( IERC20[] calldata erc20s, uint256[] calldata amounts ) external isPermitted(OWNER_ROLE) { uint256 length = erc20s.length; if (amounts.length != length) revert InvalidArrayLength(); for (uint256 i; i < length; ) { _withdrawERC20(erc20s[i], amounts[i]); unchecked { ++i; } } } // @notice Withdraw multiple ERC721 ids for a single ERC721 contract // @param erc721 The address of the ERC721 contract // @param ids An array of ids that are to be withdrawn function withdrawERC721s( IERC721 erc721, uint256[] calldata ids ) external isPermitted(OWNER_ROLE) { _withdrawERC721s(erc721, ids); } // @notice Withdraw multiple ERC1155 ids for a single ERC1155 contract // @param erc1155 The address of the ERC155 contract // @param ids An array of ids that are to be withdrawn // @param amounts An array of amounts per id function withdrawERC1155s( IERC1155 erc1155, uint256[] calldata ids, uint256[] calldata amounts ) external isPermitted(OWNER_ROLE) { _withdrawERC1155s(erc1155, ids, amounts); } // @notice Revoke approval on an array of assets and operators // @dev Works for ERC20s, ERC721s, and ERC1155s // @param notes A tuple that contains the protocol id, token address, and array of operators function revokeApprovals(ApprovalNote[] calldata notes) external isPermitted(OWNER_ROLE) { ApprovalNote memory note; Protocol protocol; uint256 length = notes.length; for (uint256 i; i < length; ) { note = notes[i]; protocol = note.protocol; if (protocol == Protocol.ERC20) { _revokeERC20Approvals(IERC20(note.token), note.operators); } else if (protocol == Protocol.ERC721) { _revokeERC721Approvals(IERC721(note.token), note.operators); } else if (protocol == Protocol.ERC1155) { _revokeERC1155Approvals(IERC1155(note.token), note.operators); } unchecked { ++i; } } } // @notice Revoke approval of an ERC20 for an array of operators // @param erc20 The address of the ERC20 token // @param operators The array of operators to have approval revoked function revokeERC20Approvals( IERC20 erc20, address[] calldata operators ) external isPermitted(OWNER_ROLE) { _revokeERC20Approvals(erc20, operators); } // @notice Revoke approval of an ERC721 for an array of operators // @param erc721 The address of the ERC721 token // @param operators The array of operators to have approval revoked function revokeERC721Approvals( IERC721 erc721, address[] calldata operators ) external isPermitted(OWNER_ROLE) { _revokeERC721Approvals(erc721, operators); } // @notice Revoke approval of an ERC1155 for an array of operators // @param erc1155 The address of the ERC1155 token // @param operators The array of operators to have approval revoked function revokeERC1155Approvals( IERC1155 erc1155, address[] calldata operators ) external isPermitted(OWNER_ROLE) { _revokeERC1155Approvals(erc1155, operators); } //////////////////////////////////////////////////// // Internal functions ////////////////////////////// //////////////////////////////////////////////////// function _withdrawETH(uint256 amount) internal { (bool success, ) = msg.sender.call{value: amount}(""); if (!success) revert WithdrawFailed(); } function _withdrawERC20(IERC20 erc20, uint256 amount) internal { erc20.safeTransfer(msg.sender, amount); } function _withdrawERC721s(IERC721 erc721, uint256[] memory ids) internal { uint256 length = ids.length; for (uint256 i; i < length; ) { erc721.safeTransferFrom(address(this), msg.sender, ids[i]); unchecked { ++i; } } } function _withdrawERC1155s(IERC1155 erc1155, uint256[] memory ids, uint256[] memory amounts) internal { // safeBatchTransferFrom will validate the array lengths erc1155.safeBatchTransferFrom(address(this), msg.sender, ids, amounts, ""); } function _revokeERC20Approvals(IERC20 erc20, address[] memory operators) internal { uint256 length = operators.length; for (uint256 i; i < length; ) { erc20.safeApprove(operators[i], 0); unchecked { ++i; } } } function _revokeERC721Approvals(IERC721 erc721, address[] memory operators) internal { uint256 length = operators.length; for (uint256 i; i < length; ) { erc721.setApprovalForAll(operators[i], false); unchecked { ++i; } } } function _revokeERC1155Approvals(IERC1155 erc1155, address[] memory operators) internal { uint256 length = operators.length; for (uint256 i; i < length; ) { erc1155.setApprovalForAll(operators[i], false); unchecked { ++i; } } } //////////////////////////////////////////////////// // Fallback functions ////////////////////////////// //////////////////////////////////////////////////// receive() external payable {} }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.16; import "./ACL.sol"; import "./Roles.sol"; // @notice The OWNER_ROLE must be set in the importing contract's constructor or initialize function abstract contract AccessController is ACL, Roles { using StorageAPI for bytes32; event PermissionSet(bytes32 role, address account, bool permission); error UnsafeSetting(); error InvalidAccount(); // @notice Sets user permission over a role // @param role The bytes32 value of the role // @param account The address of the account // @param permission The permission status function setPermission( bytes32 role, address account, bool permission ) external isPermitted(OWNER_ROLE) { if (account == address(0)) revert InvalidAccount(); if (role == OWNER_ROLE && account == msg.sender && permission == false) revert UnsafeSetting(); _setPermission(role, account, permission); } // @notice Internal function to set user permission over a role // @param role The bytes32 value of the role // @param account The address of the account // @param permission The permission status function _setPermission(bytes32 role, address account, bool permission) internal { bytes32 key = _getKey(role, account); key.setBool(permission); emit PermissionSet(role, account, permission); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.16; library CommandBuilder { uint256 constant IDX_VARIABLE_LENGTH = 0x80; uint256 constant IDX_VALUE_MASK = 0x7f; uint256 constant IDX_END_OF_ARGS = 0xff; uint256 constant IDX_USE_STATE = 0xfe; uint256 constant IDX_ARRAY_START = 0xfd; uint256 constant IDX_TUPLE_START = 0xfc; uint256 constant IDX_DYNAMIC_END = 0xfb; function buildInputs( bytes[] memory state, bytes4 selector, bytes32 indices, uint256 indicesLength ) internal view returns (bytes memory ret) { uint256 idx; // The current command index uint256 offsetIdx; // The index of the current free offset uint256 count; // Number of bytes in whole ABI encoded message uint256 free; // Pointer to first free byte in tail part of message uint256[] memory dynamicLengths = new uint256[](10); // Optionally store the length of all dynamic types (a command cannot fit more than 10 dynamic types) bytes memory stateData; // Optionally encode the current state if the call requires it // Determine the length of the encoded data for (uint256 i; i < indicesLength; ) { idx = uint8(indices[i]); if (idx == IDX_END_OF_ARGS) { indicesLength = i; break; } if (idx & IDX_VARIABLE_LENGTH != 0) { if (idx == IDX_USE_STATE) { if (stateData.length == 0) { stateData = abi.encode(state); } unchecked { count += stateData.length; } } else { (dynamicLengths, offsetIdx, count, i) = setupDynamicType( state, indices, dynamicLengths, idx, offsetIdx, count, i ); } } else { count = setupStaticVariable(state, count, idx); } unchecked { free += 32; ++i; } } // Encode it ret = new bytes(count + 4); assembly { mstore(add(ret, 32), selector) } offsetIdx = 0; // Use count to track current memory slot assembly { count := add(ret, 36) } for (uint256 i; i < indicesLength; ) { idx = uint8(indices[i]); if (idx & IDX_VARIABLE_LENGTH != 0) { if (idx == IDX_USE_STATE) { assembly { mstore(count, free) } memcpy(stateData, 32, ret, free + 4, stateData.length - 32); unchecked { free += stateData.length - 32; } } else if (idx == IDX_ARRAY_START) { // Start of dynamic type, put pointer in current slot assembly { mstore(count, free) } (offsetIdx, free, i, ) = encodeDynamicArray( ret, state, indices, dynamicLengths, offsetIdx, free, i ); } else if (idx == IDX_TUPLE_START) { // Start of dynamic type, put pointer in current slot assembly { mstore(count, free) } (offsetIdx, free, i, ) = encodeDynamicTuple( ret, state, indices, dynamicLengths, offsetIdx, free, i ); } else { // Variable length data uint256 argLen = state[idx & IDX_VALUE_MASK].length; // Put a pointer in the current slot and write the data to first free slot assembly { mstore(count, free) } memcpy( state[idx & IDX_VALUE_MASK], 0, ret, free + 4, argLen ); unchecked { free += argLen; } } } else { // Fixed length data (length previously checked to be 32 bytes) bytes memory stateVar = state[idx & IDX_VALUE_MASK]; // Write the data to current slot assembly { mstore(count, mload(add(stateVar, 32))) } } unchecked { count += 32; ++i; } } } function setupStaticVariable( bytes[] memory state, uint256 count, uint256 idx ) internal pure returns (uint256 newCount) { require( state[idx & IDX_VALUE_MASK].length == 32, "Static state variables must be 32 bytes" ); unchecked { newCount = count + 32; } } function setupDynamicVariable( bytes[] memory state, uint256 count, uint256 idx ) internal pure returns (uint256 newCount) { bytes memory arg = state[idx & IDX_VALUE_MASK]; // Validate the length of the data in state is a multiple of 32 uint256 argLen = arg.length; require( argLen != 0 && argLen % 32 == 0, "Dynamic state variables must be a multiple of 32 bytes" ); // Add the length of the value, rounded up to the next word boundary, plus space for pointer unchecked { newCount = count + argLen + 32; } } function setupDynamicType( bytes[] memory state, bytes32 indices, uint256[] memory dynamicLengths, uint256 idx, uint256 offsetIdx, uint256 count, uint256 index ) internal view returns ( uint256[] memory newDynamicLengths, uint256 newOffsetIdx, uint256 newCount, uint256 newIndex ) { if (idx == IDX_ARRAY_START) { (newDynamicLengths, newOffsetIdx, newCount, newIndex) = setupDynamicArray( state, indices, dynamicLengths, offsetIdx, count, index ); } else if (idx == IDX_TUPLE_START) { (newDynamicLengths, newOffsetIdx, newCount, newIndex) = setupDynamicTuple( state, indices, dynamicLengths, offsetIdx, count, index ); } else { newDynamicLengths = dynamicLengths; newOffsetIdx = offsetIdx; newIndex = index; newCount = setupDynamicVariable(state, count, idx); } } function setupDynamicArray( bytes[] memory state, bytes32 indices, uint256[] memory dynamicLengths, uint256 offsetIdx, uint256 count, uint256 index ) internal view returns ( uint256[] memory newDynamicLengths, uint256 newOffsetIdx, uint256 newCount, uint256 newIndex ) { // Current idx is IDX_ARRAY_START, next idx will contain the array length unchecked { newIndex = index + 1; newCount = count + 32; } uint256 idx = uint8(indices[newIndex]); require( state[idx & IDX_VALUE_MASK].length == 32, "Array length must be 32 bytes" ); (newDynamicLengths, newOffsetIdx, newCount, newIndex) = setupDynamicTuple( state, indices, dynamicLengths, offsetIdx, newCount, newIndex ); } function setupDynamicTuple( bytes[] memory state, bytes32 indices, uint256[] memory dynamicLengths, uint256 offsetIdx, uint256 count, uint256 index ) internal view returns ( uint256[] memory newDynamicLengths, uint256 newOffsetIdx, uint256 newCount, uint256 newIndex ) { uint256 idx; uint256 offset; newDynamicLengths = dynamicLengths; // Progress to first index of the data and progress the next offset idx unchecked { newIndex = index + 1; newOffsetIdx = offsetIdx + 1; newCount = count + 32; } while (newIndex < 32) { idx = uint8(indices[newIndex]); if (idx & IDX_VARIABLE_LENGTH != 0) { if (idx == IDX_DYNAMIC_END) { newDynamicLengths[offsetIdx] = offset; // explicit return saves gas ¯\_(ツ)_/¯ return (newDynamicLengths, newOffsetIdx, newCount, newIndex); } else { require(idx != IDX_USE_STATE, "Cannot use state from inside dynamic type"); (newDynamicLengths, newOffsetIdx, newCount, newIndex) = setupDynamicType( state, indices, newDynamicLengths, idx, newOffsetIdx, newCount, newIndex ); } } else { newCount = setupStaticVariable(state, newCount, idx); } unchecked { offset += 32; ++newIndex; } } revert("Dynamic type was not properly closed"); } function encodeDynamicArray( bytes memory ret, bytes[] memory state, bytes32 indices, uint256[] memory dynamicLengths, uint256 offsetIdx, uint256 currentSlot, uint256 index ) internal view returns ( uint256 newOffsetIdx, uint256 newSlot, uint256 newIndex, uint256 length ) { // Progress to array length metadata unchecked { newIndex = index + 1; newSlot = currentSlot + 32; } // Encode array length uint256 idx = uint8(indices[newIndex]); // Array length value previously checked to be 32 bytes bytes memory stateVar = state[idx & IDX_VALUE_MASK]; assembly { mstore(add(add(ret, 36), currentSlot), mload(add(stateVar, 32))) } (newOffsetIdx, newSlot, newIndex, length) = encodeDynamicTuple( ret, state, indices, dynamicLengths, offsetIdx, newSlot, newIndex ); unchecked { length += 32; // Increase length to account for array length metadata } } function encodeDynamicTuple( bytes memory ret, bytes[] memory state, bytes32 indices, uint256[] memory dynamicLengths, uint256 offsetIdx, uint256 currentSlot, uint256 index ) internal view returns ( uint256 newOffsetIdx, uint256 newSlot, uint256 newIndex, uint256 length ) { uint256 idx; uint256 argLen; uint256 freePointer = dynamicLengths[offsetIdx]; // The pointer to the next free slot unchecked { newSlot = currentSlot + freePointer; // Update the next slot newOffsetIdx = offsetIdx + 1; // Progress to next offsetIdx newIndex = index + 1; // Progress to first index of the data } // Shift currentSlot to correct location in memory assembly { currentSlot := add(add(ret, 36), currentSlot) } while (newIndex < 32) { idx = uint8(indices[newIndex]); if (idx & IDX_VARIABLE_LENGTH != 0) { if (idx == IDX_DYNAMIC_END) { break; } else if (idx == IDX_ARRAY_START) { // Start of dynamic type, put pointer in current slot assembly { mstore(currentSlot, freePointer) } (newOffsetIdx, newSlot, newIndex, argLen) = encodeDynamicArray( ret, state, indices, dynamicLengths, newOffsetIdx, newSlot, newIndex ); unchecked { freePointer += argLen; length += (argLen + 32); // data + pointer } } else if (idx == IDX_TUPLE_START) { // Start of dynamic type, put pointer in current slot assembly { mstore(currentSlot, freePointer) } (newOffsetIdx, newSlot, newIndex, argLen) = encodeDynamicTuple( ret, state, indices, dynamicLengths, newOffsetIdx, newSlot, newIndex ); unchecked { freePointer += argLen; length += (argLen + 32); // data + pointer } } else { // Variable length data argLen = state[idx & IDX_VALUE_MASK].length; // Start of dynamic type, put pointer in current slot assembly { mstore(currentSlot, freePointer) } memcpy( state[idx & IDX_VALUE_MASK], 0, ret, newSlot + 4, argLen ); unchecked { newSlot += argLen; freePointer += argLen; length += (argLen + 32); // data + pointer } } } else { // Fixed length data (length previously checked to be 32 bytes) bytes memory stateVar = state[idx & IDX_VALUE_MASK]; // Write to first free slot assembly { mstore(currentSlot, mload(add(stateVar, 32))) } unchecked { length += 32; } } unchecked { currentSlot += 32; ++newIndex; } } } function writeOutputs( bytes[] memory state, bytes1 index, bytes memory output ) internal pure returns (bytes[] memory) { uint256 idx = uint8(index); if (idx == IDX_END_OF_ARGS) return state; if (idx & IDX_VARIABLE_LENGTH != 0) { if (idx == IDX_USE_STATE) { state = abi.decode(output, (bytes[])); } else { require(idx & IDX_VALUE_MASK < state.length, "Index out-of-bounds"); // Check the first field is 0x20 (because we have only a single return value) uint256 argPtr; assembly { argPtr := mload(add(output, 32)) } require( argPtr == 32, "Only one return value permitted (variable)" ); assembly { // Overwrite the first word of the return data with the length - 32 mstore(add(output, 32), sub(mload(output), 32)) // Insert a pointer to the return data, starting at the second word, into state mstore( add(add(state, 32), mul(and(idx, IDX_VALUE_MASK), 32)), add(output, 32) ) } } } else { require(idx & IDX_VALUE_MASK < state.length, "Index out-of-bounds"); // Single word require( output.length == 32, "Only one return value permitted (static)" ); state[idx & IDX_VALUE_MASK] = output; } return state; } function writeTuple( bytes[] memory state, bytes1 index, bytes memory output ) internal view { uint256 idx = uint8(index); if (idx == IDX_END_OF_ARGS) return; bytes memory entry = state[idx & IDX_VALUE_MASK] = new bytes(output.length + 32); memcpy(output, 0, entry, 32, output.length); assembly { let l := mload(output) mstore(add(entry, 32), l) } } function memcpy( bytes memory src, uint256 srcIdx, bytes memory dest, uint256 destIdx, uint256 len ) internal view { assembly { pop( staticcall( gas(), 4, add(add(src, 32), srcIdx), len, add(add(dest, 32), destIdx), len ) ) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred 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`. * * 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; /** * @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 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * 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 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 the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/utils/ERC721Holder.sol) pragma solidity ^0.8.0; import "../IERC721Receiver.sol"; /** * @dev Implementation of the {IERC721Receiver} interface. * * Accepts all token transfers. * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}. */ contract ERC721Holder is IERC721Receiver { /** * @dev See {IERC721Receiver-onERC721Received}. * * Always returns `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address, address, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC721Received.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol) pragma solidity ^0.8.0; import "./ERC1155Receiver.sol"; /** * Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens. * * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be * stuck. * * @dev _Available since v3.1._ */ contract ERC1155Holder is ERC1155Receiver { function onERC1155Received( address, address, uint256, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] memory, uint256[] memory, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.16; import "../libraries/StorageAPI.sol"; abstract contract ACL { using StorageAPI for bytes32; error NotPermitted(); modifier isPermitted(bytes32 role) { bool permitted = _getPermission(role, msg.sender); // TODO: support GSN/Account abstraction if (!permitted) revert NotPermitted(); _; } // @notice Gets user permission for a role // @param role The bytes32 value of the role // @param account The address of the account // @return The permission status function getPermission(bytes32 role, address account) external view returns (bool) { return _getPermission(role, account); } // @notice Internal function to get user permission for a role // @param role The bytes32 value of the role // @param account The address of the account // @return The permission status function _getPermission(bytes32 role, address account) internal view returns (bool) { bytes32 key = _getKey(role, account); return key.getBool(); } // @notice Internal function to get the key for the storage slot // @param role The bytes32 value of the role // @param account The address of the account // @return The bytes32 storage slot function _getKey(bytes32 role, address account) internal pure returns (bytes32) { return keccak256(abi.encode(role, account)); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.16; abstract contract Roles { // Using same slot generation technique as eip-1967 -- https://eips.ethereum.org/EIPS/eip-1967 bytes32 public constant OWNER_ROLE = bytes32(uint256(keccak256("enso.access.roles.owner")) - 1); bytes32 public constant EXECUTOR_ROLE = bytes32(uint256(keccak256("enso.access.roles.executor")) - 1); bytes32 public constant MODULE_ROLE = bytes32(uint256(keccak256("enso.access.roles.module")) - 1); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^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 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 // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Receiver.sol) pragma solidity ^0.8.0; import "../IERC1155Receiver.sol"; import "../../../utils/introspection/ERC165.sol"; /** * @dev _Available since v3.1._ */ abstract contract ERC1155Receiver is ERC165, IERC1155Receiver { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.16; library StorageAPI { function setBytes(bytes32 key, bytes memory data) internal { bytes32 slot = keccak256(abi.encodePacked(key)); assembly { let length := mload(data) switch gt(length, 0x1F) case 0x00 { sstore(key, or(mload(add(data, 0x20)), mul(length, 2))) } case 0x01 { sstore(key, add(mul(length, 2), 1)) for { let i := 0 } lt(mul(i, 0x20), length) { i := add(i, 0x01) } { sstore(add(slot, i), mload(add(data, mul(add(i, 1), 0x20)))) } } } } function setBytes32(bytes32 key, bytes32 val) internal { assembly { sstore(key, val) } } function setAddress(bytes32 key, address a) internal { assembly { sstore(key, a) } } function setUint256(bytes32 key, uint256 val) internal { assembly { sstore(key, val) } } function setInt256(bytes32 key, int256 val) internal { assembly { sstore(key, val) } } function setBool(bytes32 key, bool val) internal { assembly { sstore(key, val) } } function getBytes(bytes32 key) internal view returns (bytes memory data) { bytes32 slot = keccak256(abi.encodePacked(key)); assembly { let length := sload(key) switch and(length, 0x01) case 0x00 { let decodedLength := div(and(length, 0xFF), 2) mstore(data, decodedLength) mstore(add(data, 0x20), and(length, not(0xFF))) mstore(0x40, add(data, 0x40)) } case 0x01 { let decodedLength := div(length, 2) let i := 0 mstore(data, decodedLength) for { } lt(mul(i, 0x20), decodedLength) { i := add(i, 0x01) } { mstore(add(add(data, 0x20), mul(i, 0x20)), sload(add(slot, i))) } mstore(0x40, add(data, add(0x20, mul(i, 0x20)))) } } } function getBytes32(bytes32 key) internal view returns (bytes32 val) { assembly { val := sload(key) } } function getAddress(bytes32 key) internal view returns (address a) { assembly { a := sload(key) } } function getUint256(bytes32 key) internal view returns (uint256 val) { assembly { val := sload(key) } } function getInt256(bytes32 key) internal view returns (int256 val) { assembly { val := sload(key) } } function getBool(bytes32 key) internal view returns (bool val) { assembly { val := sload(key) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
{ "remappings": [ "@ensdomains/=lib/shortcuts-contracts/node_modules/@ensdomains/", "@ensofinance/=lib/shortcuts-contracts/node_modules/@ensofinance/", "@ethereum-waffle/=lib/shortcuts-contracts/node_modules/@ethereum-waffle/", "@openzeppelin/=lib/shortcuts-contracts/node_modules/@openzeppelin/", "@rari-capital/=lib/shortcuts-contracts/node_modules/@rari-capital/", "clones-with-immutable-args/=lib/shortcuts-contracts/node_modules/clones-with-immutable-args/", "ds-test/=lib/forge-std/lib/ds-test/src/", "enso-weiroll/=lib/enso-weiroll/contracts/", "eth-gas-reporter/=lib/shortcuts-contracts/node_modules/eth-gas-reporter/", "forge-std/=lib/forge-std/src/", "hardhat-deploy/=lib/shortcuts-contracts/node_modules/hardhat-deploy/", "hardhat/=lib/shortcuts-contracts/node_modules/hardhat/", "shortcuts-contracts/=lib/shortcuts-contracts/contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
[{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"command_index","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"string","name":"message","type":"string"}],"name":"ExecutionFailed","type":"error"},{"inputs":[],"name":"InvalidAccount","type":"error"},{"inputs":[],"name":"InvalidArrayLength","type":"error"},{"inputs":[],"name":"NotPermitted","type":"error"},{"inputs":[],"name":"UnsafeSetting","type":"error"},{"inputs":[],"name":"WithdrawFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"permission","type":"bool"}],"name":"PermissionSet","type":"event"},{"inputs":[],"name":"EXECUTOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MODULE_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OWNER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"commands","type":"bytes32[]"},{"internalType":"bytes[]","name":"state","type":"bytes[]"}],"name":"executeShortcut","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"getPermission","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"enum MinimalWallet.Protocol","name":"protocol","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address[]","name":"operators","type":"address[]"}],"internalType":"struct MinimalWallet.ApprovalNote[]","name":"notes","type":"tuple[]"}],"name":"revokeApprovals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC1155","name":"erc1155","type":"address"},{"internalType":"address[]","name":"operators","type":"address[]"}],"name":"revokeERC1155Approvals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"erc20","type":"address"},{"internalType":"address[]","name":"operators","type":"address[]"}],"name":"revokeERC20Approvals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"erc721","type":"address"},{"internalType":"address[]","name":"operators","type":"address[]"}],"name":"revokeERC721Approvals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"permission","type":"bool"}],"name":"setPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"enum MinimalWallet.Protocol","name":"protocol","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"internalType":"struct MinimalWallet.TransferNote[]","name":"notes","type":"tuple[]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC1155","name":"erc1155","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"withdrawERC1155s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20[]","name":"erc20s","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"withdrawERC20s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"erc721","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"withdrawERC721s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6080346100fc57601f61241d38819003918201601f19168301926001600160401b03929091838511838610176100e65781602092849260409788528339810103126100fc57516001600160a01b038116908190036100fc57825191602083017f3fbe42dcb277543d3741131fe04ce9fb205e3b7154603a23a25efd63ed2c9e1b9081815283868601528585526060850192858410908411176100e6577ff7682c7604ab581823c6ee4b22f8283179771e57c8115328f4a698be07430a41946060946001938460a094878b528451902055855260808201520152a15161231b90816101028239f35b634e487b7160e01b600052604160045260246000fd5b600080fdfe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806301ffc9a71461014b57806307bd0265146101465780630fe786e114610141578063150b7a021461013c57806331b455a51461013757806356255c5314610132578063599e4c701461012d57806360d6c7cf146101285780638a2685a914610123578063a4508b1f1461011e578063a6b520c014610119578063bc197c8114610114578063dedd65241461010f578063e1084a131461010a578063e58378bb14610105578063e5cb370314610100578063f14210a6146100fb578063f23a6e61146100f65763fdb09f3c0361000e57610cf7565b610bf4565b610bc9565b610bbb565b610b80565b610a6f565b6108ff565b610845565b610787565b6106ff565b610689565b61060e565b610514565b6104d5565b610436565b6103dd565b610266565b6101ea565b346101a15760203660031901126101a15760043563ffffffff60e01b81168091036101a157602090630271189760e51b8114908115610190575b506040519015158152f35b6301ffc9a760e01b14905038610185565b600080fd5b60009103126101a157565b634e487b7160e01b600052601160045260246000fd5b6000198101919082116101d657565b6101b1565b601f198101919082116101d657565b346101a15760003660031901126101a15760206040517fd931ed5eea9427443091b211e417e6f83bd1d1a5235f4e7adbb05b556120802f8152f35b6001600160a01b038116036101a157565b9181601f840112156101a1578235916001600160401b0383116101a1576020808501948460051b0101116101a157565b346101a15760403660031901126101a15760043561028381610225565b6024356001600160401b0381116101a1576102a2903690600401610236565b6102ae92919233610d9a565b54156102c957610019926102c3913691610f8d565b906112bc565b6040516339218f3b60e01b8152600490fd5b634e487b7160e01b600052604160045260246000fd5b608081019081106001600160401b0382111761030c57604052565b6102db565b606081019081106001600160401b0382111761030c57604052565b6001600160401b03811161030c57604052565b604081019081106001600160401b0382111761030c57604052565b90601f801991011681019081106001600160401b0382111761030c57604052565b6001600160401b03811161030c57601f01601f191660200190565b81601f820112156101a1578035906103ad8261037b565b926103bb604051948561035a565b828452602083830101116101a157816000926020809301838601378301015290565b346101a15760803660031901126101a1576103f9600435610225565b610404602435610225565b6064356001600160401b0381116101a157610423903690600401610396565b50604051630a85bd0160e11b8152602090f35b346101a15760403660031901126101a15760043561045381610225565b6024356001600160401b0381116101a157610472903690600401610236565b61047e92919233610d9a565b54156102c95761001992610493913691610f8d565b9061123f565b9060406003198301126101a1576004356104b281610225565b91602435906001600160401b0382116101a1576104d191600401610236565b9091565b346101a1576104e336610499565b6104ef92919233610d9a565b54156102c957610019926105049136916107d9565b906110ef565b801515036101a157565b346101a15760603660031901126101a15760043560243561053481610225565b604435916105418361050a565b61054a33610d9a565b54156102c9576001600160a01b0382169283156105fc577f3fbe42dcb277543d3741131fe04ce9fb205e3b7154603a23a25efd63ed2c9e1b8214806105f3575b806105eb575b6105d9577ff7682c7604ab581823c6ee4b22f8283179771e57c8115328f4a698be07430a4193816105c360609585610de7565b55604051928352602083015215156040820152a1005b604051630337b9b360e41b8152600490fd5b508015610590565b5033841461058a565b604051630da30f6560e31b8152600490fd5b346101a15760403660031901126101a157602061063860243561063081610225565b600435610de7565b546040519015158152f35b60406003198201126101a1576001600160401b03916004358381116101a1578261066f91600401610236565b939093926024359182116101a1576104d191600401610236565b346101a15761069736610643565b906106a133610d9a565b54156102c9578282036106ed5760005b8381106106ba57005b806106e76106cb6001938789610f3a565b356106d581610225565b6106e0838787610f3a565b35906110ae565b016106b1565b604051634ec4810560e11b8152600490fd5b346101a15760603660031901126101a15760043561071c81610225565b6001600160401b03906024358281116101a15761073d903690600401610236565b926044359081116101a157610756903690600401610236565b919061076133610d9a565b54156102c957610779610781926100199636916107d9565b9236916107d9565b916111b3565b346101a15760003660031901126101a15760206040517fc3757b2598fc76eee6f032de6e0c1a33b52273c8afc630e889b8d170f8a26b1a8152f35b6001600160401b03811161030c5760051b60200190565b92916107e4826107c2565b916107f2604051938461035a565b829481845260208094019160051b81019283116101a157905b8282106108185750505050565b8135815290830190830161080b565b9080601f830112156101a157816020610842933591016107d9565b90565b346101a15760a03660031901126101a157610861600435610225565b61086c602435610225565b6001600160401b036044358181116101a15761088c903690600401610827565b506064358181116101a1576108a5903690600401610827565b506084359081116101a1576108be903690600401610396565b5060405163bc197c8160e01b8152602090f35b0390f35b60206003198201126101a157600435906001600160401b0382116101a1576104d191600401610236565b346101a15761090d366108d5565b9061091733610d9a565b54156102c957610925610e0d565b5060005b82811061093257005b610945610940828585610e49565b610e7d565b9081519161095283610ef9565b61095b83610ef9565b8261098b57606001518051909250600019016106ed5761098561097f600193610f19565b51611083565b01610929565b61099483610ef9565b6001928084036109e757506060810151928351036106ed57602001516001926109e2916109db906109d5906001600160a01b03165b6001600160a01b031690565b91610f19565b51906110ae565b610985565b600193506109f481610ef9565b60028103610a24575060408101516020909101516109e29190610a1f906001600160a01b03166109c9565b6110ef565b80610a30600392610ef9565b14610a3c575b50610985565b60408101516060820151602090920151610a69929190610a64906001600160a01b03166109c9565b6111b3565b38610a36565b346101a157610a7d366108d5565b90610a8733610d9a565b54156102c957610a95610f4a565b5060005b828110610aa257005b610ab5610ab0828585610f6b565b610fe5565b90815191610ac283610ef9565b610acb83610ef9565b600192808403610b0457506020810151610afe9190604090610af5906001600160a01b03166109c9565b9101519061123f565b01610a99565b610b0d81610ef9565b60028103610b4357506020810151610b3e9190604090610b35906001600160a01b03166109c9565b910151906112bc565b610afe565b80610b4f600392610ef9565b14610b5b575b50610afe565b6020810151610b7a9190604090610b35906001600160a01b03166109c9565b38610b55565b346101a15760003660031901126101a15760206040517f3fbe42dcb277543d3741131fe04ce9fb205e3b7154603a23a25efd63ed2c9e1b8152f35b346101a1576102a236610499565b346101a15760203660031901126101a157610be333610d9a565b54156102c957610019600435611083565b346101a15760a03660031901126101a157610c10600435610225565b610c1b602435610225565b6084356001600160401b0381116101a157610c3a903690600401610396565b5060405163f23a6e6160e01b8152602090f35b60005b838110610c605750506000910152565b8181015183820152602001610c50565b90602091610c8981518092818552858086019101610c4d565b601f01601f1916010190565b602080820190808352835180925260408301928160408460051b8301019501936000915b848310610cc95750505050505090565b9091929394958480610ce7600193603f198682030187528a51610c70565b9801930193019194939290610cb9565b610d0036610643565b9290739008d19f58aabd9ed0d60971565aa8510560ab4133036102c957610d26846107c2565b93610d34604051958661035a565b8085526020918286019160051b8101913683116101a15781905b838210610d6f576108d1610d63898989611578565b60405191829182610c95565b81356001600160401b0381116101a1578591610d8f839236908701610396565b815201910190610d4e565b604080517f3fbe42dcb277543d3741131fe04ce9fb205e3b7154603a23a25efd63ed2c9e1b602082019081526001600160a01b0390931681830152908152610de181610311565b51902090565b60408051602081019283526001600160a01b0390931683820152825290610de181610311565b60405190610e1a826102f1565b6060808360008152600060208201528160408201520152565b634e487b7160e01b600052603260045260246000fd5b9190811015610e6b5760051b81013590607e19813603018212156101a1570190565b610e33565b359060048210156101a157565b6080813603126101a15760405190610e94826102f1565b610e9d81610e70565b82526020810135610ead81610225565b60208301526001600160401b039060408101358281116101a157610ed49036908301610827565b604084015260608101359182116101a157610ef191369101610827565b606082015290565b60041115610f0357565b634e487b7160e01b600052602160045260246000fd5b805115610e6b5760200190565b8051821015610e6b5760209160051b010190565b9190811015610e6b5760051b0190565b60405190610f5782610311565b606060408360008152600060208201520152565b9190811015610e6b5760051b81013590605e19813603018212156101a1570190565b9291610f98826107c2565b91610fa6604051938461035a565b829481845260208094019160051b81019283116101a157905b828210610fcc5750505050565b8380918335610fda81610225565b815201910190610fbf565b6060813603126101a15760405190610ffc82610311565b61100581610e70565b8252602081013561101581610225565b60208301526040810135906001600160401b0382116101a1570136601f820112156101a15761104b903690602081359101610f8d565b604082015290565b3d1561107e573d906110648261037b565b91611072604051938461035a565b82523d6000602084013e565b606090565b600080808093335af1611094611053565b501561109c57565b604051631d42c86760e21b8152600490fd5b906110e1916040519163a9059cbb60e01b60208401523360248401526044830152604482526110dc826102f1565b611348565b565b6040513d6000823e3d90fd5b81519060005b8281106111025750505050565b6001600160a01b038216906111178186610f26565b51823b156101a157600092606484926040519586938492632142170760e11b845230600485015233602485015260448401525af191821561117a57600192611161575b50016110f5565b8061116e6111749261032c565b806101a6565b3861115a565b6110e3565b90815180825260208080930193019160005b82811061119f575050505090565b835185529381019392810192600101611191565b6001600160a01b031691823b156101a1576112159260009283602061120294826040519889978896631759616b60e11b885230600489015233602489015260a0604489015260a488019061117f565b600319938488830301606489015261117f565b85810392830160848701525201925af1801561117a576112325750565b8061116e6110e19261032c565b81519160005b8381106112525750505050565b6001906112b66112a26112b06001600160a01b036112708588610f26565b5160405163095ea7b360e01b602082015291166001600160a01b03166024820152600060448201529182906064820190565b03601f19810183528261035a565b85611348565b01611245565b81519060005b8281106112cf5750505050565b6001600160a01b0382811691906112e68287610f26565b511691803b156101a15760405163a22cb46560e01b81526001600160a01b03939093166004840152600060248401819052908390604490829084905af191821561117a57600192611339575b50016112c2565b6113429061032c565b38611332565b6040516113a6916001600160a01b03166113618261033f565b6000806020958685527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656487860152868151910182855af16113a0611053565b91611428565b8051806113b257505050565b818391810103126101a1578101516113c98161050a565b156113d15750565b6084906040519062461bcd60e51b82526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152fd5b9192901561148a575081511561143c575090565b3b156114455790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b82519091501561149d5750805190602001fd5b60405162461bcd60e51b8152602060048201529081906114c1906024830190610c70565b0390fd5b156114cc57565b60405162461bcd60e51b815260206004820152601660248201527556616c7565206d75737420626520333220627974657360501b6044820152606490fd5b60208151910151906020811061151e575090565b6000199060200360031b1b1690565b6040519061153a8261033f565b60078252662ab735b737bbb760c91b6020830152565b9081526001600160a01b03909116602082015260606040820181905261084292910190610c70565b9060005b8181106115895750505090565b611594818385610f3a565b604091903560d881901c83811615928361184757600101936115b7858789610f3a565b3560205b60038481166001810361170e57506000928392602092508683166116f6576115ee916001600160e01b031989168e6118ca565b905b81519101826001600160a01b0388165af19361160a611053565b94905b85911561165f5750505060801615611640576001929161163a9160581b6001600160f81b03191687612205565b0161157c565b90600192956116599260ff60f81b9060581b169061215a565b9361163a565b8491876114c1928861166f61152d565b93604491828151116116b8575b5050506000146116a957935b5163ef3dcb2f60e01b81529384936001600160a01b03169060048501611550565b6116b2906101c7565b93611688565b60206116cf60046116c884612283565b930161150a565b0361167c576116e06024830161150a565b146116ec575b8061167c565b01925086806116e6565b50607f6117079160f81c168c610f26565b51906115f0565b60028103611776575060009283926020925086831661175e5761173c916001600160e01b031989168e6118ca565b905b815191016001600160a01b0387165afa93611757611053565b949061160d565b50607f61176f9160f81c168c610f26565b519061173e565b03611810576000918291607f906117938d838560f81c1690610f26565b51928d6117ad6020956117a8878251146114c5565b61150a565b93858a161587146117f757506117c56117db936101c7565b9160081b906001600160e01b03198b16906118ca565b915b82519201906001600160a01b0388165af193611757611053565b919050611809925060f01c168d610f26565b51916117dd565b825162461bcd60e51b815260206004820152601060248201526f496e76616c69642063616c6c7479706560801b6044820152606490fd5b93602883901b6001600160d01b031760066115bb565b6040519061016082018281106001600160401b0382111761030c57604052600a8252610140366020840137565b90600482018092116101d657565b906118a28261037b565b6118af604051918261035a565b82815280926118c0601f199161037b565b0190602036910137565b939290600080816118d961185d565b9060609281905b878210611a2e575b50506118f66118fb9161188a565b611898565b97602094858a0152600060248a019281955b8887106119205750505050505050505050565b87871015610e6b5787908c8b808a1a6080811615611a0d5760fe810361197a57505090611967600193928289526119568361188a565b6119608b516101db565b918b612271565b875101601f1901955b019601959361190d565b939795929390919060fd81036119ab5750918484928860019c9561199f978a52611df2565b50979195909593611970565b60fc81036119c85750918484928860019c9561199f978a52611e3a565b6119f5925060019491607f611a06929a95989a16906119e7828b610f26565b5151948592858d528b610f26565b5190611a008561188a565b9161225f565b0195611970565b84939892506001949150607f611a24911688610f26565b5101518152611970565b9092949160209081851015610e6b5789851a60ff8114611acf578c6080821615611abb578b9060fe8303611a9d57505050855115611a7a575b90600191865101935b01959301906118e0565b94506001906112a2611a948d604051928391858301610c95565b95909150611a67565b98611aaf95929160019895979a611b58565b94919390939296611a70565b9060019392611ac992611ae5565b93611a70565b5093975091949291506118f690506118fb6118e8565b611af690607f602093941690610f26565b515103611b035760200190565b60405162461bcd60e51b815260206004820152602760248201527f537461746963207374617465207661726961626c6573206d75737420626520336044820152663220627974657360c81b6064820152608490fd5b90969594939260fd8103611b78575095611b729596611c27565b90919293565b60fc8103611b8c575095611b729596611d01565b9196509194939291611ba191607f1690610f26565b515180151580611c1c575b15611bb8570160200191565b60405162461bcd60e51b815260206004820152603660248201527f44796e616d6963207374617465207661726961626c6573206d7573742062652060448201527561206d756c7469706c65206f6620333220627974657360501b6064820152608490fd5b50601f811615611bac565b9291909394600101936020851015610e6b576020611c4a607f83881a1686610f26565b515103611c5e576020611b72960193611d01565b60405162461bcd60e51b815260206004820152601d60248201527f4172726179206c656e677468206d7573742062652033322062797465730000006044820152606490fd5b15611caa57565b60405162461bcd60e51b815260206004820152602960248201527f43616e6e6f74207573652073746174652066726f6d20696e736964652064796e604482015268616d6963207479706560b81b6064820152608490fd5b6001808501976020968701978201969095600094909392915b808910611d725760405162461bcd60e51b8152602060048201526024808201527f44796e616d6963207479706520776173206e6f742070726f7065726c7920636c6044820152631bdcd95960e21b6064820152608490fd5b81891a6080811615611dd85760fb8103611d9c575050505050611d959083610f26565b5293929190565b99849b8b83989985879e98611dbb611dc0989f97999a60fe1415611ca3565b611b58565b9b929b9a919a96909a9b975b01950197909291611d1a565b90611dec8495939a979b9282959385611ae5565b9a611dcc565b939291909495600101946020861015610e6b576020611e2c9781611e1b607f868b1a1685610f26565b510151602482890101520194611e3a565b929391929091602090910190565b939596929091600094611e4d8884610f26565b51936024600180878b019b019b0198830101915b602094858a1015611f8357848a1a6080811615611f5d5760fb8103611e8a575050505050505050565b9b8c60fd889d939598979c94969b999e14600014611ed5575090611eb592918d8b52848c8988611df2565b929c919b978301909501989101956001915b019301979291939093611e61565b9091929394955060fc8114600014611f13575091611efd918b9594938d8b52848c8988611e3a565b929c919b97830190950198910195600191611ec7565b9a89878e83949f9e95611f51607f6001989b9a999b1694611f46611f378787610f26565b51519687968796879452610f26565b518b611a008561188a565b019d0198010198611ec7565b95600192949981611f77607f8295979a9e999e168a610f26565b5101518b520198611ec7565b50505050505050565b15611f9357565b60405162461bcd60e51b8152602060048201526013602482015272496e646578206f75742d6f662d626f756e647360681b6044820152606490fd5b15611fd557565b60405162461bcd60e51b815260206004820152602860248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015267287374617469632960c01b6064820152608490fd5b1561203257565b60405162461bcd60e51b815260206004820152602a60248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015269287661726961626c652960b01b6064820152608490fd5b60209081818403126101a15780516001600160401b03918282116101a157019083601f830112156101a15781516120c0816107c2565b946040926120d08451978861035a565b828752858088019360051b860101948286116101a157868101935b8685106120fd57505050505050505090565b84518381116101a15782019084603f830112156101a15788820151906121228261037b565b61212e8951918261035a565b828152868984860101116101a15761214f8b949385948b8685019101610c4d565b8152019401936120eb565b91908060f81c60ff81146121ff5760808116156121c75760fe810361218f57505061084291506020808251830101910161208a565b6020916121a5610fe092607f8751911610611f8c565b828401936121b58486511461202b565b51601f1901845260f31c168301015290565b6121fb929150607f16906121dd84518310611f8c565b6121ea6020825114611fce565b6121f48285610f26565b5282610f26565b5090565b50505090565b9060f81c60ff811461225a57825190602082018092116101d657602092607f61223061224394611898565b92169161223d8383610f26565b52610f26565b51918051604084018184840160045afa5051910152565b505050565b916020809185930101920160045afa50565b910160200190829060400160045afa50565b9081516043198082018281116101d6579360445b8381106122a5575b50505050565b8151811015610e6b57818101602001516001600160f81b031916156122cc57600101612297565b93945050905081019081116101d657903880808061229f56fea264697066735822122069ab4b955d676afe34efe2a531e2dbda38b223105e1debfbff5cf84997e8863364736f6c63430008130033000000000000000000000000826e0bb2276271efdf2a500597f37b94f6c153ba
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806301ffc9a71461014b57806307bd0265146101465780630fe786e114610141578063150b7a021461013c57806331b455a51461013757806356255c5314610132578063599e4c701461012d57806360d6c7cf146101285780638a2685a914610123578063a4508b1f1461011e578063a6b520c014610119578063bc197c8114610114578063dedd65241461010f578063e1084a131461010a578063e58378bb14610105578063e5cb370314610100578063f14210a6146100fb578063f23a6e61146100f65763fdb09f3c0361000e57610cf7565b610bf4565b610bc9565b610bbb565b610b80565b610a6f565b6108ff565b610845565b610787565b6106ff565b610689565b61060e565b610514565b6104d5565b610436565b6103dd565b610266565b6101ea565b346101a15760203660031901126101a15760043563ffffffff60e01b81168091036101a157602090630271189760e51b8114908115610190575b506040519015158152f35b6301ffc9a760e01b14905038610185565b600080fd5b60009103126101a157565b634e487b7160e01b600052601160045260246000fd5b6000198101919082116101d657565b6101b1565b601f198101919082116101d657565b346101a15760003660031901126101a15760206040517fd931ed5eea9427443091b211e417e6f83bd1d1a5235f4e7adbb05b556120802f8152f35b6001600160a01b038116036101a157565b9181601f840112156101a1578235916001600160401b0383116101a1576020808501948460051b0101116101a157565b346101a15760403660031901126101a15760043561028381610225565b6024356001600160401b0381116101a1576102a2903690600401610236565b6102ae92919233610d9a565b54156102c957610019926102c3913691610f8d565b906112bc565b6040516339218f3b60e01b8152600490fd5b634e487b7160e01b600052604160045260246000fd5b608081019081106001600160401b0382111761030c57604052565b6102db565b606081019081106001600160401b0382111761030c57604052565b6001600160401b03811161030c57604052565b604081019081106001600160401b0382111761030c57604052565b90601f801991011681019081106001600160401b0382111761030c57604052565b6001600160401b03811161030c57601f01601f191660200190565b81601f820112156101a1578035906103ad8261037b565b926103bb604051948561035a565b828452602083830101116101a157816000926020809301838601378301015290565b346101a15760803660031901126101a1576103f9600435610225565b610404602435610225565b6064356001600160401b0381116101a157610423903690600401610396565b50604051630a85bd0160e11b8152602090f35b346101a15760403660031901126101a15760043561045381610225565b6024356001600160401b0381116101a157610472903690600401610236565b61047e92919233610d9a565b54156102c95761001992610493913691610f8d565b9061123f565b9060406003198301126101a1576004356104b281610225565b91602435906001600160401b0382116101a1576104d191600401610236565b9091565b346101a1576104e336610499565b6104ef92919233610d9a565b54156102c957610019926105049136916107d9565b906110ef565b801515036101a157565b346101a15760603660031901126101a15760043560243561053481610225565b604435916105418361050a565b61054a33610d9a565b54156102c9576001600160a01b0382169283156105fc577f3fbe42dcb277543d3741131fe04ce9fb205e3b7154603a23a25efd63ed2c9e1b8214806105f3575b806105eb575b6105d9577ff7682c7604ab581823c6ee4b22f8283179771e57c8115328f4a698be07430a4193816105c360609585610de7565b55604051928352602083015215156040820152a1005b604051630337b9b360e41b8152600490fd5b508015610590565b5033841461058a565b604051630da30f6560e31b8152600490fd5b346101a15760403660031901126101a157602061063860243561063081610225565b600435610de7565b546040519015158152f35b60406003198201126101a1576001600160401b03916004358381116101a1578261066f91600401610236565b939093926024359182116101a1576104d191600401610236565b346101a15761069736610643565b906106a133610d9a565b54156102c9578282036106ed5760005b8381106106ba57005b806106e76106cb6001938789610f3a565b356106d581610225565b6106e0838787610f3a565b35906110ae565b016106b1565b604051634ec4810560e11b8152600490fd5b346101a15760603660031901126101a15760043561071c81610225565b6001600160401b03906024358281116101a15761073d903690600401610236565b926044359081116101a157610756903690600401610236565b919061076133610d9a565b54156102c957610779610781926100199636916107d9565b9236916107d9565b916111b3565b346101a15760003660031901126101a15760206040517fc3757b2598fc76eee6f032de6e0c1a33b52273c8afc630e889b8d170f8a26b1a8152f35b6001600160401b03811161030c5760051b60200190565b92916107e4826107c2565b916107f2604051938461035a565b829481845260208094019160051b81019283116101a157905b8282106108185750505050565b8135815290830190830161080b565b9080601f830112156101a157816020610842933591016107d9565b90565b346101a15760a03660031901126101a157610861600435610225565b61086c602435610225565b6001600160401b036044358181116101a15761088c903690600401610827565b506064358181116101a1576108a5903690600401610827565b506084359081116101a1576108be903690600401610396565b5060405163bc197c8160e01b8152602090f35b0390f35b60206003198201126101a157600435906001600160401b0382116101a1576104d191600401610236565b346101a15761090d366108d5565b9061091733610d9a565b54156102c957610925610e0d565b5060005b82811061093257005b610945610940828585610e49565b610e7d565b9081519161095283610ef9565b61095b83610ef9565b8261098b57606001518051909250600019016106ed5761098561097f600193610f19565b51611083565b01610929565b61099483610ef9565b6001928084036109e757506060810151928351036106ed57602001516001926109e2916109db906109d5906001600160a01b03165b6001600160a01b031690565b91610f19565b51906110ae565b610985565b600193506109f481610ef9565b60028103610a24575060408101516020909101516109e29190610a1f906001600160a01b03166109c9565b6110ef565b80610a30600392610ef9565b14610a3c575b50610985565b60408101516060820151602090920151610a69929190610a64906001600160a01b03166109c9565b6111b3565b38610a36565b346101a157610a7d366108d5565b90610a8733610d9a565b54156102c957610a95610f4a565b5060005b828110610aa257005b610ab5610ab0828585610f6b565b610fe5565b90815191610ac283610ef9565b610acb83610ef9565b600192808403610b0457506020810151610afe9190604090610af5906001600160a01b03166109c9565b9101519061123f565b01610a99565b610b0d81610ef9565b60028103610b4357506020810151610b3e9190604090610b35906001600160a01b03166109c9565b910151906112bc565b610afe565b80610b4f600392610ef9565b14610b5b575b50610afe565b6020810151610b7a9190604090610b35906001600160a01b03166109c9565b38610b55565b346101a15760003660031901126101a15760206040517f3fbe42dcb277543d3741131fe04ce9fb205e3b7154603a23a25efd63ed2c9e1b8152f35b346101a1576102a236610499565b346101a15760203660031901126101a157610be333610d9a565b54156102c957610019600435611083565b346101a15760a03660031901126101a157610c10600435610225565b610c1b602435610225565b6084356001600160401b0381116101a157610c3a903690600401610396565b5060405163f23a6e6160e01b8152602090f35b60005b838110610c605750506000910152565b8181015183820152602001610c50565b90602091610c8981518092818552858086019101610c4d565b601f01601f1916010190565b602080820190808352835180925260408301928160408460051b8301019501936000915b848310610cc95750505050505090565b9091929394958480610ce7600193603f198682030187528a51610c70565b9801930193019194939290610cb9565b610d0036610643565b9290739008d19f58aabd9ed0d60971565aa8510560ab4133036102c957610d26846107c2565b93610d34604051958661035a565b8085526020918286019160051b8101913683116101a15781905b838210610d6f576108d1610d63898989611578565b60405191829182610c95565b81356001600160401b0381116101a1578591610d8f839236908701610396565b815201910190610d4e565b604080517f3fbe42dcb277543d3741131fe04ce9fb205e3b7154603a23a25efd63ed2c9e1b602082019081526001600160a01b0390931681830152908152610de181610311565b51902090565b60408051602081019283526001600160a01b0390931683820152825290610de181610311565b60405190610e1a826102f1565b6060808360008152600060208201528160408201520152565b634e487b7160e01b600052603260045260246000fd5b9190811015610e6b5760051b81013590607e19813603018212156101a1570190565b610e33565b359060048210156101a157565b6080813603126101a15760405190610e94826102f1565b610e9d81610e70565b82526020810135610ead81610225565b60208301526001600160401b039060408101358281116101a157610ed49036908301610827565b604084015260608101359182116101a157610ef191369101610827565b606082015290565b60041115610f0357565b634e487b7160e01b600052602160045260246000fd5b805115610e6b5760200190565b8051821015610e6b5760209160051b010190565b9190811015610e6b5760051b0190565b60405190610f5782610311565b606060408360008152600060208201520152565b9190811015610e6b5760051b81013590605e19813603018212156101a1570190565b9291610f98826107c2565b91610fa6604051938461035a565b829481845260208094019160051b81019283116101a157905b828210610fcc5750505050565b8380918335610fda81610225565b815201910190610fbf565b6060813603126101a15760405190610ffc82610311565b61100581610e70565b8252602081013561101581610225565b60208301526040810135906001600160401b0382116101a1570136601f820112156101a15761104b903690602081359101610f8d565b604082015290565b3d1561107e573d906110648261037b565b91611072604051938461035a565b82523d6000602084013e565b606090565b600080808093335af1611094611053565b501561109c57565b604051631d42c86760e21b8152600490fd5b906110e1916040519163a9059cbb60e01b60208401523360248401526044830152604482526110dc826102f1565b611348565b565b6040513d6000823e3d90fd5b81519060005b8281106111025750505050565b6001600160a01b038216906111178186610f26565b51823b156101a157600092606484926040519586938492632142170760e11b845230600485015233602485015260448401525af191821561117a57600192611161575b50016110f5565b8061116e6111749261032c565b806101a6565b3861115a565b6110e3565b90815180825260208080930193019160005b82811061119f575050505090565b835185529381019392810192600101611191565b6001600160a01b031691823b156101a1576112159260009283602061120294826040519889978896631759616b60e11b885230600489015233602489015260a0604489015260a488019061117f565b600319938488830301606489015261117f565b85810392830160848701525201925af1801561117a576112325750565b8061116e6110e19261032c565b81519160005b8381106112525750505050565b6001906112b66112a26112b06001600160a01b036112708588610f26565b5160405163095ea7b360e01b602082015291166001600160a01b03166024820152600060448201529182906064820190565b03601f19810183528261035a565b85611348565b01611245565b81519060005b8281106112cf5750505050565b6001600160a01b0382811691906112e68287610f26565b511691803b156101a15760405163a22cb46560e01b81526001600160a01b03939093166004840152600060248401819052908390604490829084905af191821561117a57600192611339575b50016112c2565b6113429061032c565b38611332565b6040516113a6916001600160a01b03166113618261033f565b6000806020958685527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656487860152868151910182855af16113a0611053565b91611428565b8051806113b257505050565b818391810103126101a1578101516113c98161050a565b156113d15750565b6084906040519062461bcd60e51b82526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152fd5b9192901561148a575081511561143c575090565b3b156114455790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b82519091501561149d5750805190602001fd5b60405162461bcd60e51b8152602060048201529081906114c1906024830190610c70565b0390fd5b156114cc57565b60405162461bcd60e51b815260206004820152601660248201527556616c7565206d75737420626520333220627974657360501b6044820152606490fd5b60208151910151906020811061151e575090565b6000199060200360031b1b1690565b6040519061153a8261033f565b60078252662ab735b737bbb760c91b6020830152565b9081526001600160a01b03909116602082015260606040820181905261084292910190610c70565b9060005b8181106115895750505090565b611594818385610f3a565b604091903560d881901c83811615928361184757600101936115b7858789610f3a565b3560205b60038481166001810361170e57506000928392602092508683166116f6576115ee916001600160e01b031989168e6118ca565b905b81519101826001600160a01b0388165af19361160a611053565b94905b85911561165f5750505060801615611640576001929161163a9160581b6001600160f81b03191687612205565b0161157c565b90600192956116599260ff60f81b9060581b169061215a565b9361163a565b8491876114c1928861166f61152d565b93604491828151116116b8575b5050506000146116a957935b5163ef3dcb2f60e01b81529384936001600160a01b03169060048501611550565b6116b2906101c7565b93611688565b60206116cf60046116c884612283565b930161150a565b0361167c576116e06024830161150a565b146116ec575b8061167c565b01925086806116e6565b50607f6117079160f81c168c610f26565b51906115f0565b60028103611776575060009283926020925086831661175e5761173c916001600160e01b031989168e6118ca565b905b815191016001600160a01b0387165afa93611757611053565b949061160d565b50607f61176f9160f81c168c610f26565b519061173e565b03611810576000918291607f906117938d838560f81c1690610f26565b51928d6117ad6020956117a8878251146114c5565b61150a565b93858a161587146117f757506117c56117db936101c7565b9160081b906001600160e01b03198b16906118ca565b915b82519201906001600160a01b0388165af193611757611053565b919050611809925060f01c168d610f26565b51916117dd565b825162461bcd60e51b815260206004820152601060248201526f496e76616c69642063616c6c7479706560801b6044820152606490fd5b93602883901b6001600160d01b031760066115bb565b6040519061016082018281106001600160401b0382111761030c57604052600a8252610140366020840137565b90600482018092116101d657565b906118a28261037b565b6118af604051918261035a565b82815280926118c0601f199161037b565b0190602036910137565b939290600080816118d961185d565b9060609281905b878210611a2e575b50506118f66118fb9161188a565b611898565b97602094858a0152600060248a019281955b8887106119205750505050505050505050565b87871015610e6b5787908c8b808a1a6080811615611a0d5760fe810361197a57505090611967600193928289526119568361188a565b6119608b516101db565b918b612271565b875101601f1901955b019601959361190d565b939795929390919060fd81036119ab5750918484928860019c9561199f978a52611df2565b50979195909593611970565b60fc81036119c85750918484928860019c9561199f978a52611e3a565b6119f5925060019491607f611a06929a95989a16906119e7828b610f26565b5151948592858d528b610f26565b5190611a008561188a565b9161225f565b0195611970565b84939892506001949150607f611a24911688610f26565b5101518152611970565b9092949160209081851015610e6b5789851a60ff8114611acf578c6080821615611abb578b9060fe8303611a9d57505050855115611a7a575b90600191865101935b01959301906118e0565b94506001906112a2611a948d604051928391858301610c95565b95909150611a67565b98611aaf95929160019895979a611b58565b94919390939296611a70565b9060019392611ac992611ae5565b93611a70565b5093975091949291506118f690506118fb6118e8565b611af690607f602093941690610f26565b515103611b035760200190565b60405162461bcd60e51b815260206004820152602760248201527f537461746963207374617465207661726961626c6573206d75737420626520336044820152663220627974657360c81b6064820152608490fd5b90969594939260fd8103611b78575095611b729596611c27565b90919293565b60fc8103611b8c575095611b729596611d01565b9196509194939291611ba191607f1690610f26565b515180151580611c1c575b15611bb8570160200191565b60405162461bcd60e51b815260206004820152603660248201527f44796e616d6963207374617465207661726961626c6573206d7573742062652060448201527561206d756c7469706c65206f6620333220627974657360501b6064820152608490fd5b50601f811615611bac565b9291909394600101936020851015610e6b576020611c4a607f83881a1686610f26565b515103611c5e576020611b72960193611d01565b60405162461bcd60e51b815260206004820152601d60248201527f4172726179206c656e677468206d7573742062652033322062797465730000006044820152606490fd5b15611caa57565b60405162461bcd60e51b815260206004820152602960248201527f43616e6e6f74207573652073746174652066726f6d20696e736964652064796e604482015268616d6963207479706560b81b6064820152608490fd5b6001808501976020968701978201969095600094909392915b808910611d725760405162461bcd60e51b8152602060048201526024808201527f44796e616d6963207479706520776173206e6f742070726f7065726c7920636c6044820152631bdcd95960e21b6064820152608490fd5b81891a6080811615611dd85760fb8103611d9c575050505050611d959083610f26565b5293929190565b99849b8b83989985879e98611dbb611dc0989f97999a60fe1415611ca3565b611b58565b9b929b9a919a96909a9b975b01950197909291611d1a565b90611dec8495939a979b9282959385611ae5565b9a611dcc565b939291909495600101946020861015610e6b576020611e2c9781611e1b607f868b1a1685610f26565b510151602482890101520194611e3a565b929391929091602090910190565b939596929091600094611e4d8884610f26565b51936024600180878b019b019b0198830101915b602094858a1015611f8357848a1a6080811615611f5d5760fb8103611e8a575050505050505050565b9b8c60fd889d939598979c94969b999e14600014611ed5575090611eb592918d8b52848c8988611df2565b929c919b978301909501989101956001915b019301979291939093611e61565b9091929394955060fc8114600014611f13575091611efd918b9594938d8b52848c8988611e3a565b929c919b97830190950198910195600191611ec7565b9a89878e83949f9e95611f51607f6001989b9a999b1694611f46611f378787610f26565b51519687968796879452610f26565b518b611a008561188a565b019d0198010198611ec7565b95600192949981611f77607f8295979a9e999e168a610f26565b5101518b520198611ec7565b50505050505050565b15611f9357565b60405162461bcd60e51b8152602060048201526013602482015272496e646578206f75742d6f662d626f756e647360681b6044820152606490fd5b15611fd557565b60405162461bcd60e51b815260206004820152602860248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015267287374617469632960c01b6064820152608490fd5b1561203257565b60405162461bcd60e51b815260206004820152602a60248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015269287661726961626c652960b01b6064820152608490fd5b60209081818403126101a15780516001600160401b03918282116101a157019083601f830112156101a15781516120c0816107c2565b946040926120d08451978861035a565b828752858088019360051b860101948286116101a157868101935b8685106120fd57505050505050505090565b84518381116101a15782019084603f830112156101a15788820151906121228261037b565b61212e8951918261035a565b828152868984860101116101a15761214f8b949385948b8685019101610c4d565b8152019401936120eb565b91908060f81c60ff81146121ff5760808116156121c75760fe810361218f57505061084291506020808251830101910161208a565b6020916121a5610fe092607f8751911610611f8c565b828401936121b58486511461202b565b51601f1901845260f31c168301015290565b6121fb929150607f16906121dd84518310611f8c565b6121ea6020825114611fce565b6121f48285610f26565b5282610f26565b5090565b50505090565b9060f81c60ff811461225a57825190602082018092116101d657602092607f61223061224394611898565b92169161223d8383610f26565b52610f26565b51918051604084018184840160045afa5051910152565b505050565b916020809185930101920160045afa50565b910160200190829060400160045afa50565b9081516043198082018281116101d6579360445b8381106122a5575b50505050565b8151811015610e6b57818101602001516001600160f81b031916156122cc57600101612297565b93945050905081019081116101d657903880808061229f56fea264697066735822122069ab4b955d676afe34efe2a531e2dbda38b223105e1debfbff5cf84997e8863364736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000826e0bb2276271efdf2a500597f37b94f6c153ba
-----Decoded View---------------
Arg [0] : owner (address): 0x826e0BB2276271eFdF2a500597f37b94f6c153bA
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000826e0bb2276271efdf2a500597f37b94f6c153ba
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 39.50% | $1 | 369.8862 | $369.89 | |
ETH | 21.41% | $1 | 200.4578 | $200.46 | |
ETH | 14.49% | $0.995202 | 136.3334 | $135.68 | |
ETH | 6.21% | $0.999643 | 58.1681 | $58.15 | |
ETH | 4.27% | $0.999643 | 39.9921 | $39.98 | |
ETH | 3.04% | $13.58 | 2.0985 | $28.5 | |
ETH | 2.91% | $3,268.95 | 0.00833 | $27.23 | |
ETH | 2.13% | $0.998531 | 19.9961 | $19.97 | |
ETH | 1.61% | $0.000002 | 9,248,976.8329 | $15.06 | |
ETH | 0.67% | $3,665.65 | 0.00171947 | $6.3 | |
ETH | 0.57% | $0.26637 | 19.9862 | $5.32 | |
ETH | 0.53% | $0.997264 | 4.9956 | $4.98 | |
ETH | 0.53% | $0.070476 | 69.9894 | $4.93 | |
ETH | 0.34% | $3,217.64 | 0.00099915 | $3.21 | |
ETH | 0.31% | <$0.000001 | 9,996,297.6601 | $2.94 | |
ETH | 0.28% | $0.264867 | 9.8598 | $2.61 | |
ETH | 0.26% | $19.87 | 0.123 | $2.44 | |
ETH | 0.18% | $3,329.29 | 0.00049342 | $1.64 | |
ETH | 0.14% | $0.517225 | 2.4837 | $1.28 | |
ETH | 0.13% | $68,675 | 0.00001741 | $1.2 | |
ETH | 0.09% | <$0.000001 | 9,993,780.0612 | $0.8454 | |
ETH | Ether (ETH) | 0.09% | $3,268.95 | 0.00024997 | $0.817151 |
ETH | 0.08% | $0.000891 | 799.2307 | $0.7124 | |
ETH | 0.07% | $0.12305 | 4.9895 | $0.6139 | |
ETH | 0.06% | $0.000095 | 5,467.8717 | $0.5171 | |
ETH | 0.04% | $49.1 | 0.00697573 | $0.3425 | |
ETH | 0.03% | $0.000138 | 1,994.6513 | $0.2757 | |
ETH | 0.02% | $1.12 | 0.1894 | $0.2121 | |
ETH | 0.01% | <$0.000001 | 421,489.9175 | $0.1091 | |
ETH | 0.01% | $4 | 0.0254 | $0.1015 | |
MATIC | <0.01% | $0.516044 | 0.0001 | $0.000052 |
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.
Address QR Code
My Address - Private Name Tag or Note
My Name Tag:
Private Note:
Please DO NOT store any passwords or private keys here.
The compiled contract might be susceptible to VerbatimInvalidDeduplication (low-severity), FullInlinerNonExpressionSplitArgumentEvaluationOrder (low-severity), MissingSideEffectsOnSelectorAccess (low-severity) Solidity Compiler Bugs.
Connect a Wallet
Connect a Wallet
Connect a Wallet
Before You Copy
This website uses cookies to improve your experience. By continuing to use this website, you agree to its Terms and Privacy Policy.