Polygon Sponsored slots available. Book your slot here!
Overview
POL Balance
0 POL
POL Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
HybridViciERC20
Compiler Version
v0.8.24+commit.e11b9ed9
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "ECDSA.sol"; import "BaseViciContract.sol"; import "ERC677ReceiverInterface.sol"; import "EIP712.sol"; import "Monotonic.sol"; import "AbstractPluginExecutor.sol"; import "IModularViciERC20.sol"; import "IModularERC20Ops.sol"; import "ViciERC20RolesErrorsEvents.sol"; /** * @title Hybrid ViciERC20 * @author Josh Davis * @notice Adds plugin capability to ViciNFT's ERC20 contract while preserving the existing memory layout. */ /// @dev the HybridViciERC20Base is where the existing memory layout is preserved abstract contract HybridViciERC20Base is BaseViciContract, EIP712, IERC20Metadata, IBridgeable, IERC677 { // solhint-disable-next-line var-name-mixedcase bytes32 internal constant _PERMIT_TYPEHASH = keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ); /** * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`. * However, to ensure consistency with the upgradeable transpiler, we will continue * to reserve a slot. * @custom:oz-renamed-from _PERMIT_TYPEHASH */ // solhint-disable-next-line var-name-mixedcase bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT; mapping(address => Monotonic.Increaser) internal _nonces; string public name; string public symbol; uint8 public decimals; IModularERC20Ops public tokenData; bool public isMain; address public vault; /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[43] private __gap; } contract HybridViciERC20 is HybridViciERC20Base, AbstractPluginExecutor, ViciERC20RolesErrorsEvents { using Monotonic for Monotonic.Increaser; // Only the contract owner may add or remove plugins function checkPluginManagerPermission( address sender ) internal view virtual override { accessServer.enforceIsMyOwner(sender); } function supportsInterface( bytes4 interfaceId ) public view virtual override(ViciAccess, AbstractPluginExecutor) returns (bool) { return ViciAccess.supportsInterface(interfaceId) || AbstractPluginExecutor.supportsInterface(interfaceId) || interfaceId == type(IModularViciERC20).interfaceId; } /* ################################################################ * Initialization * ##############################################################*/ /** * @dev Use this one when deploying for the first time on a new chain. * @dev Use reinit when upgrading from a v1 token * @param _accessServer The Access Server contract * @param _tokenData The ERC20 Operations contract. You MUST set this contract as the owner of that contract. * @param _name the name of the token. * @param _symbol the token symbol. * @param _decimals the number of decimals. */ function initialize( IAccessServer _accessServer, IModularERC20Ops _tokenData, string calldata _name, string calldata _symbol, uint8 _decimals, bool _isMain ) public virtual reinitializer(2) { __ViciERC20_init( _accessServer, _tokenData, _name, _symbol, _decimals, _isMain ); } function __ViciERC20_init( IAccessServer _accessServer, IModularERC20Ops _tokenData, string calldata _name, string calldata _symbol, uint8 _decimals, bool _isMain ) internal onlyInitializing { EIP712.__EIP712_init(_name, "1"); BaseViciContract.__BaseViciContract_init(_accessServer); __ViciERC20_init_unchained( _tokenData, _name, _symbol, _decimals, _isMain ); } function __ViciERC20_init_unchained( IModularERC20Ops _tokenData, string calldata _name, string calldata _symbol, uint8 _decimals, bool _isMain ) internal onlyInitializing { tokenData = _tokenData; name = _name; symbol = _symbol; decimals = _decimals; __ViciCoinV02_reinit(_isMain); } /** * @dev Use this one when upgrading from a v1 token * @dev Use initialize when deploying for the first time on a new chain. */ function reinit(bool _isMain) public reinitializer(2) { __ViciCoinV02_reinit(_isMain); } function __ViciCoinV02_reinit(bool _isMain) internal onlyInitializing { isMain = _isMain; if (isMain) { vault = address(tokenData); } } /* ################################################################ * Queries * ##############################################################*/ /** * @notice Returns the total maximum possible tokens. */ function maxSupply() public view virtual returns (uint256) { return tokenData.getMaxSupply(); } /** * @inheritdoc IERC20 */ function totalSupply() public view virtual returns (uint256) { return tokenData.totalSupply(); } function circulatingSupply() public view virtual returns (uint256) { if (isMain) { return totalSupply() - balanceOf(vault); } return totalSupply(); } /** * @notice Returns the total maximum possible tokens. */ function availableSupply() public view virtual returns (uint256) { return tokenData.availableSupply(); } /** * @dev see IERC20 */ function balanceOf( address owner ) public view virtual returns (uint256 balance) { return tokenData.balanceOf(owner); } /** * @dev Returns the number of distict owners. * @dev use with `getOwnerAtIndex()` to iterate. */ function getOwnerCount() public view virtual returns (uint256) { return tokenData.ownerCount(); } /** * @dev Returns the address of the owner at the index. * @dev use with `ownerCount()` to iterate. * * @param index the index into the list of owners * * Requirements * - `index` MUST be less than the number of owners. */ function getOwnerAtIndex( uint256 index ) public view virtual returns (address) { return tokenData.ownerAtIndex(index); } /* ################################################################ * Bridging / Transferring * ##############################################################*/ /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer( address toAddress, uint256 amount ) external virtual override pluggable returns (bool) { return _doTransfer(_msgSender(), _msgSender(), toAddress, amount); } /** * @dev See {IERC20-transferFrom}. * @dev See {safeTransferFrom}. * * Requirements * * - `fromAddress` and `toAddress` MUST NOT be the zero address. * - `toAddress`, `fromAddress`, and calling user MUST NOT be banned. * - `_tokenId` MUST belong to `fromAddress`. * - Calling user must be the `fromAddress` or be approved by the `fromAddress`. * - `_tokenId` must exist * * @inheritdoc IERC20 */ function transferFrom( address fromAddress, address toAddress, uint256 amount ) external virtual override pluggable returns (bool) { return _doTransfer(_msgSender(), fromAddress, toAddress, amount); } /** * @inheritdoc IERC677 */ function transferAndCall( address to, uint256 value, bytes calldata data ) external virtual override pluggable returns (bool success) { success = _doTransfer(_msgSender(), _msgSender(), to, value); ERC677ReceiverInterface receiver = ERC677ReceiverInterface(to); receiver.onTokenTransfer(_msgSender(), value, data); } /** * Requirements: * - caller MUST be a registered bridge contract * - * * @inheritdoc IBridgeable */ function sentToBridge( BridgeArgs calldata args ) external payable pluggable onlyRole(BRIDGE_CONTRACT) { if (isMain) { _doTransfer(args.caller, args.fromAddress, vault, args.amount); } else { _doBurn(args.caller, args.fromAddress, args.amount); } emit SentToBridge( args.fromAddress, args.toAddress, 1, args.amount, args.caller, args.remoteChainId ); } function receivedFromBridge( BridgeArgs calldata args ) external payable pluggable onlyRole(BRIDGE_CONTRACT) { if (isMain) { _doTransfer(vault, vault, args.toAddress, args.amount); } else { _doMint(_msgSender(), args.toAddress, args.amount); } emit ReceivedFromBridge( args.fromAddress, args.toAddress, 1, args.amount, args.caller, args.remoteChainId ); } /* ################################################################ * Approvals / Allowances * ##############################################################*/ /** * @dev See {IERC20-allowance}. */ function allowance( address owner, address spender ) public view virtual override returns (uint256) { return tokenData.allowance(owner, spender); //return _allowances[owner][spender]; } /** * Requirements * * - caller MUST be the token owner or be approved for all by the token * owner. * - `operator` MUST NOT be the zero address. * - `operator` and calling user MUST NOT be banned. * * @inheritdoc IERC20 */ function approve( address operator, uint256 amount ) external virtual override pluggable returns (bool) { return _doPermit(_msgSender(), operator, amount); } /** * @dev See {IERC20Permit-permit}. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external virtual pluggable { require(block.timestamp <= deadline, "ERC20Permit: expired deadline"); bytes32 structHash = keccak256( abi.encode( _PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline ) ); bytes32 hash = _hashTypedDataV4(structHash); address signer = ECDSA.recover(hash, v, r, s); require(signer == owner, "ERC20Permit: invalid signature"); _doPermit(owner, spender, value); } function getChainId() public view returns (uint256) { return block.chainid; } /** * @dev See {IERC20Permit-nonces}. */ function nonces(address owner) public view virtual returns (uint256) { return _nonces[owner].current(); } /** * @dev "Consume a nonce": return the current value and increment. * * _Available since v4.1._ */ function _useNonce( address owner ) internal virtual returns (uint256 current) { Monotonic.Increaser storage nonce = _nonces[owner]; current = nonce.current(); nonce.add(1); } /** * @dev See {IERC20Permit-DOMAIN_SEPARATOR}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return _domainSeparatorV4(); } /* ################################################################ * Utility Coin Functions * ##############################################################*/ /** * @notice Returns the amount of locked tokens for `account`. * @param account the user address */ function lockedBalanceOf( address account ) public view virtual returns (uint256) { return tokenData.lockedBalanceOf(account); } /** * @notice Returns the Unix timestamp when a user's locked tokens will be * released. * @param account the user address */ function lockReleaseDate( address account ) public view virtual returns (uint256) { return tokenData.lockReleaseDate(account); } /** * @notice Returns the difference between `account`'s total balance and its * locked balance. * @param account the user address */ function unlockedBalanceOf( address account ) public view virtual returns (uint256) { return tokenData.unlockedBalanceOf(account); } /* ################################################################ * Plugin Support * ##############################################################*/ /** * @param data abi-encoded function call for internal functions */ function executeFromPlugin( bytes calldata data ) public payable virtual override onlyPlugin returns (bytes memory result) { if (data.length > 4) { bytes4 func = bytes4(data[:4]); if (func == IModularERC20Ops.transfer.selector) { if (data.length != 132) { revert InvalidCallData(func); } ( address operator, address fromAddress, address toAddress, uint256 amount ) = abi.decode(data[4:], (address, address, address, uint256)); return (_doTransfer(operator, fromAddress, toAddress, amount)) ? TRUE : FALSE; } if (func == IModularERC20Ops.mint.selector) { if (data.length != 100) { revert InvalidCallData(func); } (address operator, address toAddress, uint256 amount) = abi .decode(data[4:], (address, address, uint256)); return (_doMint(operator, toAddress, amount)) ? TRUE : FALSE; } if (func == IModularERC20Ops.burn.selector) { if (data.length != 100) { revert InvalidCallData(func); } (address operator, address fromAddress, uint256 amount) = abi .decode(data[4:], (address, address, uint256)); return (_doBurn(operator, fromAddress, amount)) ? TRUE : FALSE; } if ( func == IModularERC20Ops.permit.selector ) { if (data.length != 100) { revert InvalidCallData(func); } (address owner, address spender, uint256 amount) = abi.decode( data[4:], (address, address, uint256) ); return (_doPermit(owner, spender, amount)) ? TRUE : FALSE; } if ( func == IModularERC20Ops.recoverSanctionedAssets.selector ) { if (data.length != 100) { revert InvalidCallData(func); } (address operator, address fromAddress, address toAddress) = abi .decode(data[4:], (address, address, address)); uint256 amount = tokenData.recoverSanctionedAssets( operator, fromAddress, toAddress ); emit SanctionedAssetsRecovered(fromAddress, toAddress, amount); _post_transfer_hook(fromAddress, toAddress, amount); return abi.encode(amount); } if ( func == IModularERC20Ops.airdropTimelockedTokens.selector ) { if (data.length != 164) { revert InvalidCallData(func); } ( address operator, address fromAddress, address toAddress, uint256 amount, uint256 release ) = abi.decode( data[4:], (address, address, address, uint256, uint256) ); tokenData.airdropTimelockedTokens( operator, fromAddress, toAddress, amount, release ); _post_transfer_hook(fromAddress, toAddress, amount); return TRUE; } if ( func == IModularERC20Ops.unlockLockedTokens.selector ) { if (data.length != 100) { revert InvalidCallData(func); } (address operator, address account, uint256 unlockAmount) = abi .decode(data[4:], (address, address, uint256)); tokenData.unlockLockedTokens(operator, account, unlockAmount); return TRUE; } if ( func == IModularERC20Ops.updateTimelocks.selector ) { if (data.length < 164 && (data.length - 4) % 32 != 0) { revert InvalidCallData(func); } ( address operator, uint256 release, address[] memory addresses ) = abi.decode(data[4:], (address, uint256, address[])); tokenData.updateTimelocks(operator, release, addresses); return TRUE; } if (func == IModularERC20Ops.recoverMisplacedTokens.selector) { if (data.length != 100) { revert InvalidCallData(func); } (address operator, address lostWallet, address toAddress) = abi .decode(data[4:], (address, address, address)); uint256 amount = tokenData.recoverMisplacedTokens( operator, lostWallet, toAddress ); emit LostTokensRecovered(lostWallet, toAddress, amount); _post_transfer_hook(lostWallet, toAddress, amount); return abi.encode(amount); } } return super.executeFromPlugin(data); } function _doTransfer( address operator, address fromAddress, address toAddress, uint256 amount ) internal virtual returns (bool) { tokenData.transfer(operator, fromAddress, toAddress, amount); _post_transfer_hook(fromAddress, toAddress, amount); return true; } function _doMint( address operator, address toAddress, uint256 amount ) internal virtual returns (bool) { tokenData.mint(operator, toAddress, amount); _post_mint_hook(toAddress, amount); return true; } function _doBurn( address operator, address fromAddress, uint256 amount ) internal virtual returns (bool) { tokenData.burn(operator, fromAddress, amount); _post_burn_hook(fromAddress, amount); return true; } function _doPermit( address owner, address spender, uint256 value ) internal virtual returns (bool) { tokenData.permit(owner, spender, value); emit Approval(owner, spender, value); return true; } /* ################################################################ * Hooks * ##############################################################*/ function _post_mint_hook( address toAddress, uint256 amount ) internal virtual { _post_transfer_hook(address(0), toAddress, amount); } function _post_burn_hook( address fromAddress, uint256 amount ) internal virtual { _post_transfer_hook(fromAddress, address(0), amount); } function _post_transfer_hook( address fromAddress, address toAddress, uint256 amount ) internal virtual { emit Transfer(fromAddress, toAddress, amount); } receive() external payable virtual override(BaseViciContract, AbstractPluginExecutor) {} /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "IERC20.sol"; import "IERC721.sol"; import "IERC1155.sol"; import "IAccessServer.sol"; import "Pausable.sol"; import "ViciAccess.sol"; /** * @title Base Vici Contract * @notice (c) 2023 ViciNFT https://vicinft.com/ * @author Josh Davis <[email protected]> * * @dev This abstract base contract grants the following features to subclasses * - Owner and role based access * - Ability to pause / unpause * - Rescue functions for crypto and tokens transferred to the contract */ abstract contract BaseViciContract is ViciAccess, Pausable { function __BaseViciContract_init(IAccessServer _accessServer) internal onlyInitializing { __ViciAccess_init(_accessServer); __Pausable_init(); __BaseViciContract_init_unchained(); } function __BaseViciContract_init_unchained() internal onlyInitializing {} /** * @dev Triggers stopped state. * * Requirements: * * - Calling user MUST be owner. * - The contract must not be paused. */ function pause() external onlyOwner { _pause(); } /** * @dev Returns to normal state. * * Requirements: * * - Calling user MUST be owner. * - The contract must be paused. */ function unpause() external onlyOwner { _unpause(); } function _withdrawERC20( uint256 amount, address payable toAddress, IERC20 tokenContract ) internal virtual { tokenContract.transfer(toAddress, amount); } function withdrawERC20( uint256 amount, address payable toAddress, IERC20 tokenContract ) public onlyOwner virtual { _withdrawERC20(amount, toAddress, tokenContract); } function _withdrawERC721( uint256 tokenId, address payable toAddress, IERC721 tokenContract ) internal virtual { tokenContract.safeTransferFrom(address(this), toAddress, tokenId); } function withdrawERC721( uint256 tokenId, address payable toAddress, IERC721 tokenContract ) public virtual onlyOwner { _withdrawERC721(tokenId, toAddress, tokenContract); } function _withdrawERC1155( uint256 tokenId, uint256 amount, address payable toAddress, bytes calldata data, IERC1155 tokenContract ) internal virtual { tokenContract.safeTransferFrom( address(this), toAddress, tokenId, amount, data ); } function withdrawERC1155( uint256 tokenId, uint256 amount, address payable toAddress, bytes calldata data, IERC1155 tokenContract ) public virtual onlyOwner { _withdrawERC1155(tokenId, amount, toAddress, data, tokenContract); } function _withdraw( address payable toAddress ) internal virtual { toAddress.transfer(address(this).balance); } function withdraw( address payable toAddress ) public virtual onlyOwner { _withdraw(toAddress); } receive() external payable virtual {} /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @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 value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.20; import {IERC165} from "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 address zero. * * 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 v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @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 v5.0.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.20; import {IERC165} from "IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` amount of tokens of 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 value 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 a `value` amount of tokens of type `id` from `from` to `to`. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155Received} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * * 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 `value` 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 value, bytes calldata data) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `values` 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 values, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; interface ChainalysisSanctionsList { function isSanctioned(address addr) external view returns (bool); } /** * @title Access Server Interface * @notice (c) 2023 ViciNFT https://vicinft.com/ * @author Josh Davis <[email protected]> * * @dev Interface for the AccessServer. * @dev AccessServer client contracts SHOULD refer to the server contract via * this interface. */ interface IAccessServer { /* ################################################################ * Modifiers / Rule Enforcement * ##############################################################*/ /** * @dev Throws if the account is not the resource's owner. */ function enforceIsOwner(address resource, address account) external view; /** * @dev Throws if the account is not the calling resource's owner. */ function enforceIsMyOwner(address account) external view; /** * @dev Reverts if the account is not the resource owner or doesn't have * the moderator role for the resource. */ function enforceIsModerator(address resource, address account) external view; /** * @dev Reverts if the account is not the resource owner or doesn't have * the moderator role for the calling resource. */ function enforceIsMyModerator(address account) external view; /** * @dev Reverts if the account is under OFAC sanctions or is banned for the * resource */ function enforceIsNotBanned(address resource, address account) external view; /** * @dev Reverts if the account is under OFAC sanctions or is banned for the * calling resource */ function enforceIsNotBannedForMe(address account) external view; /** * @dev Reverts the account is on the OFAC sanctions list. */ function enforceIsNotSanctioned(address account) external view; /** * @dev Reverts if the account is not the resource owner or doesn't have * the required role for the resource. */ function enforceOwnerOrRole( address resource, bytes32 role, address account ) external view; /** * @dev Reverts if the account is not the resource owner or doesn't have * the required role for the calling resource. */ function enforceOwnerOrRoleForMe(bytes32 role, address account) external view; /* ################################################################ * Administration * ##############################################################*/ /** * @dev Returns `true` if `admin` is an administrator of this AccessServer. */ function isAdministrator(address admin) external view returns (bool); /** * @dev Adds `admin` as an administrator of this AccessServer. */ function addAdministrator(address admin) external; /** * @dev Removes `admin` as an administrator of this AccessServer. */ function removeAdministrator(address admin) external; /** * @dev Returns the number of administrators of this AccessServer. * @dev Use with `getAdminAt()` to enumerate. */ function getAdminCount() external view returns (uint256); /** * @dev Returns the administrator at the index. * @dev Use with `getAdminCount()` to enumerate. */ function getAdminAt(uint256 index) external view returns (address); /** * @dev Returns the list of administrators */ function getAdmins() external view returns (address[] memory); /** * @dev returns the Chainalysis sanctions oracle. */ function sanctionsList() external view returns (ChainalysisSanctionsList); /** * @dev Sets the Chainalysis sanctions oracle. * @dev setting this to the zero address disables sanctions compliance. * @dev Don't disable sanctions compliance unless there is some problem * with the sanctions oracle. */ function setSanctionsList(ChainalysisSanctionsList _sanctionsList) external; /** * @dev Returns `true` if `account` is under OFAC sanctions. * @dev Returns `false` if sanctions compliance is disabled. */ function isSanctioned(address account) external view returns (bool); /* ################################################################ * Registration / Ownership * ##############################################################*/ /** * @dev Registers the calling resource and sets the resource owner. * @dev Grants the default administrator role for the resource to the * resource owner. * * Requirements: * - caller SHOULD be a contract * - caller MUST NOT be already registered * - `owner` MUST NOT be the zero address * - `owner` MUST NOT be globally banned * - `owner` MUST NOT be under OFAC sanctions */ function register(address owner) external; /** * @dev Returns `true` if `resource` is registered. */ function isRegistered(address resource) external view returns (bool); /** * @dev Returns the owner of `resource`. */ function getResourceOwner(address resource) external view returns (address); /** * @dev Returns the owner of the calling resource. */ function getMyOwner() external view returns (address); /** * @dev Sets the owner for the calling resource. * * Requirements: * - caller MUST be a registered resource * - `operator` MUST be the current owner * - `newOwner` MUST NOT be the zero address * - `newOwner` MUST NOT be globally banned * - `newOwner` MUST NOT be banned by the calling resource * - `newOwner` MUST NOT be under OFAC sanctions * - `newOwner` MUST NOT be the current owner */ function setMyOwner(address operator, address newOwner) external; /* ################################################################ * Role Administration * ##############################################################*/ /** * @dev Returns the admin role that controls `role` by default for all * resources. See {grantRole} and {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getGlobalRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Returns the admin role that controls `role` for a resource. * See {grantRole} and {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdminForResource(address resource, bytes32 role) external view returns (bytes32); /** * @dev Returns the admin role that controls `role` for the calling resource. * See {grantRole} and {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getMyRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Sets `adminRole` as ``role``'s admin role on as default all * resources. * * Requirements: * - caller MUST be an an administrator of this AccessServer */ function setGlobalRoleAdmin(bytes32 role, bytes32 adminRole) external; /** * @dev Sets `adminRole` as ``role``'s admin role on the calling resource. * @dev There is no set roleAdminForResource vs setRoleAdminForMe. * @dev Resources must manage their own role admins or use the global * defaults. * * Requirements: * - caller MUST be a registered resource */ function setRoleAdmin( address operator, bytes32 role, bytes32 adminRole ) external; /* ################################################################ * Checking Role Membership * ##############################################################*/ /** * @dev Returns `true` if `account` has been granted `role` as default for * all resources. */ function hasGlobalRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns `true` if `account` has been granted `role` globally or for * `resource`. */ function hasRole( address resource, bytes32 role, address account ) external view returns (bool); /** * @dev Returns `true` if `account` has been granted `role` for `resource`. */ function hasLocalRole( address resource, bytes32 role, address account ) external view returns (bool); /** * @dev Returns `true` if `account` has been granted `role` globally or for * the calling resource. */ function hasRoleForMe(bytes32 role, address account) external view returns (bool); /** * @dev Returns `true` if account` is banned globally or from `resource`. */ function isBanned(address resource, address account) external view returns (bool); /** * @dev Returns `true` if account` is banned globally or from the calling * resource. */ function isBannedForMe(address account) external view returns (bool); /** * @dev Reverts if `account` has not been granted `role` globally or for * `resource`. */ function checkRole( address resource, bytes32 role, address account ) external view; /** * @dev Reverts if `account` has not been granted `role` globally or for * the calling resource. */ function checkRoleForMe(bytes32 role, address account) external view; /* ################################################################ * Granting Roles * ##############################################################*/ /** * @dev Grants `role` to `account` as default for all resources. * @dev Warning: This function can do silly things like applying a global * ban to a resource owner. * * Requirements: * - caller MUST be an an administrator of this AccessServer * - If `role` is not BANNED_ROLE_NAME, `account` MUST NOT be banned or * under OFAC sanctions. Roles cannot be granted to such accounts. */ function grantGlobalRole(bytes32 role, address account) external; /** * @dev Grants `role` to `account` for the calling resource as `operator`. * @dev There is no set grantRoleForResource vs grantRoleForMe. * @dev Resources must manage their own roles or use the global defaults. * * Requirements: * - caller MUST be a registered resource * - `operator` SHOULD be the account that called `grantRole()` on the * calling resource. * - `operator` MUST be the resource owner or have the role admin role * for `role` on the calling resource. * - If `role` is BANNED_ROLE_NAME, `account` MUST NOT be the resource * owner. You can't ban the owner. * - If `role` is not BANNED_ROLE_NAME, `account` MUST NOT be banned or * under OFAC sanctions. Roles cannot be granted to such accounts. */ function grantRole( address operator, bytes32 role, address account ) external; /* ################################################################ * Revoking / Renouncing Roles * ##############################################################*/ /** * @dev Revokes `role` as default for all resources from `account`. * * Requirements: * - caller MUST be an an administrator of this AccessServer */ function revokeGlobalRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account` for the calling resource as * `operator`. * * Requirements: * - caller MUST be a registered resource * - `operator` SHOULD be the account that called `revokeRole()` on the * calling resource. * - `operator` MUST be the resource owner or have the role admin role * for `role` on the calling resource. * - if `role` is DEFAULT_ADMIN_ROLE, `account` MUST NOT be the calling * resource's owner. The admin role cannot be revoked from the owner. */ function revokeRole( address operator, bytes32 role, address account ) external; /** * @dev Remove the default role for yourself. You will still have the role * for any resources where it was granted individually. * * Requirements: * - caller MUST have the role they are renouncing at the global level. * - `role` MUST NOT be BANNED_ROLE_NAME. You can't unban yourself. */ function renounceRoleGlobally(bytes32 role) external; /** * @dev Renounces `role` for the calling resource as `operator`. * * Requirements: * - caller MUST be a registered resource * - `operator` SHOULD be the account that called `renounceRole()` on the * calling resource. * - `operator` MUST have the role they are renouncing on the calling * resource. * - if `role` is DEFAULT_ADMIN_ROLE, `operator` MUST NOT be the calling * resource's owner. The owner cannot renounce the admin role. * - `role` MUST NOT be BANNED_ROLE_NAME. You can't unban yourself. */ function renounceRole(address operator, bytes32 role) external; /* ################################################################ * Enumerating Role Members * ##############################################################*/ /** * @dev Returns the number of accounts that have `role` set at the global * level. * @dev Use with `getGlobalRoleMember()` to enumerate. */ function getGlobalRoleMemberCount(bytes32 role) external view returns (uint256); /** * @dev Returns one of the accounts that have `role` set at the global * level. * @dev Use with `getGlobalRoleMemberCount()` to enumerate. * * Requirements: * `index` MUST be >= 0 and < `getGlobalRoleMemberCount(role)` */ function getGlobalRoleMember(bytes32 role, uint256 index) external view returns (address); /** * @dev Returns the list of accounts that have `role` set at the global * level. */ function getGlobalRoleMembers(bytes32 role) external view returns (address[] memory); /** * @dev Returns the number of accounts that have `role` set globally or for * `resource`. * @dev Use with `getRoleMember()` to enumerate. */ function getRoleMemberCount(address resource, bytes32 role) external view returns (uint256); /** * @dev Returns one of the accounts that have `role` set globally or for * `resource`. * @dev If a role has global and local members, the global members * will be returned first. * @dev If a user has the role globally and locally, the same user will be * returned at two different indexes. * @dev If you only want locally assigned role members, start the index at * `getGlobalRoleMemberCount(role)`. * @dev Use with `getRoleMemberCount()` to enumerate. * * Requirements: * `index` MUST be >= 0 and < `getRoleMemberCount(role)` */ function getRoleMember( address resource, bytes32 role, uint256 index ) external view returns (address); /** * @dev Returns the number of accounts that have `role` set globally or for * the calling resource. * @dev Use with `getMyRoleMember()` to enumerate. */ function getMyRoleMemberCount(bytes32 role) external view returns (uint256); /** * @dev Returns one of the accounts that have `role` set globally or for * the calling resource. * @dev If a role has global and local members, the global members * will be returned first. * @dev If a user has the role globally and locally, the same user will be * returned at two different indexes. * @dev If you only want locally assigned role members, start the index at * `getGlobalRoleMemberCount(role)`. * @dev Use with `getMyRoleMemberCount()` to enumerate. * * Requirements: * `index` MUST be >= 0 and < `getMyRoleMemberCount(role)` */ function getMyRoleMember(bytes32 role, uint256 index) external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.24; import "Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. * * @dev This contract is a direct copy of OpenZeppelin's PauseableUpgradeable, * moved here, renamed, and modified to use our Context and Initializable * contracts so we don't have to deal with incompatibilities between OZ's * contracts and contracts-upgradeable packages. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.24; import "Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. * * @dev This contract is a direct copy of OpenZeppelin's ContextUpgradeable, * moved here, renamed, and modified to use our Initializable interface so we * don't have to deal with incompatibilities between OZ'` contracts and * contracts-upgradeable ` */ abstract contract Context is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.24; import "AddressUtils.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== * * @dev This contract is a direct copy of OpenZeppelin's InitializableUpgradeable, * moved here, renamed, and modified to use our AddressUtils library so we * don't have to deal with incompatibilities between OZ'` contracts and * contracts-upgradeable ` */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUtils.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require( !_initializing && _initialized < version, "Initializable: contract is already initialized" ); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Internal function that returns the initialized version. Returns `_initialized` */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Internal function that returns the initialized version. Returns `_initializing` */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.24; /** * @dev Collection of functions related to the address type * * @dev This contract is a direct copy of OpenZeppelin's AddressUpgradeable, * moved here and renamed so we don't have to deal with incompatibilities * between OZ'` contracts and contracts-upgradeable ` */ library AddressUtils { /** * @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://consensys.net/diligence/blog/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 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 pragma solidity ^0.8.24; import "ERC165.sol"; import "Context.sol"; import "AccessConstants.sol"; import "IViciAccess.sol"; import {IAccessServer} from "IAccessServer.sol"; /** * @title ViciAccess * @notice (c) 2023 ViciNFT https://vicinft.com/ * @author Josh Davis <[email protected]> * * @dev This contract implements OpenZeppelin's IAccessControl and * IAccessControlEnumerable interfaces as well as the behavior of their * Ownable contract. * @dev The differences are: * - Use of an external AccessServer contract to track roles and ownership. * - Support for OFAC sanctions compliance * - Support for a negative BANNED role * - A contract owner is automatically granted the DEFAULT ADMIN role. * - Contract owner cannot renounce ownership, can only transfer it. * - DEFAULT ADMIN role cannot be revoked from the Contract owner, nor can they * renouce that role. * @dev see `AccessControl`, `AccessControlEnumerable`, and `Ownable` for * additional documentation. */ abstract contract ViciAccess is Context, IViciAccess, ERC165 { IAccessServer public accessServer; bytes32 public constant DEFAULT_ADMIN_ROLE = DEFAULT_ADMIN; // Role for banned users. bytes32 public constant BANNED_ROLE_NAME = BANNED; // Role for moderator. bytes32 public constant MODERATOR_ROLE_NAME = MODERATOR; /* ################################################################ * Initialization * ##############################################################*/ function __ViciAccess_init( IAccessServer _accessServer ) internal onlyInitializing { __ViciAccess_init_unchained(_accessServer); } function __ViciAccess_init_unchained( IAccessServer _accessServer ) internal onlyInitializing { accessServer = _accessServer; accessServer.register(_msgSender()); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface( bytes4 interfaceId ) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || interfaceId == type(IAccessControlEnumerable).interfaceId || ERC165.supportsInterface(interfaceId); } /* ################################################################ * Checking Roles * ##############################################################*/ /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev reverts if called by an account that is not the owner and doesn't * have the required role. */ modifier onlyOwnerOrRole(bytes32 role) { enforceOwnerOrRole(role, _msgSender()); _; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { accessServer.enforceIsMyOwner(_msgSender()); _; } /** * @dev reverts if the caller is banned or on the OFAC sanctions list. */ modifier noBannedAccounts() { enforceIsNotBanned(_msgSender()); _; } /** * @dev reverts if the account is banned or on the OFAC sanctions list. */ modifier notBanned(address account) { enforceIsNotBanned(account); _; } /** * @dev Revert if the address is on the OFAC sanctions list */ modifier notSanctioned(address account) { enforceIsNotSanctioned(account); _; } /** * @dev reverts if the account is not the owner and doesn't have the required role. */ function enforceOwnerOrRole( bytes32 role, address account ) public view virtual override { if (account != owner()) { _checkRole(role, account); } } /** * @dev reverts if the account is banned or on the OFAC sanctions list. */ function enforceIsNotBanned(address account) public view virtual override { accessServer.enforceIsNotBannedForMe(account); } /** * @dev Revert if the address is on the OFAC sanctions list */ function enforceIsNotSanctioned( address account ) public view virtual override { accessServer.enforceIsNotSanctioned(account); } /** * @dev returns true if the account is banned. */ function isBanned( address account ) public view virtual override returns (bool) { return accessServer.isBannedForMe(account); } /** * @dev returns true if the account is on the OFAC sanctions list. */ function isSanctioned( address account ) public view virtual override returns (bool) { return accessServer.isSanctioned(account); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole( bytes32 role, address account ) public view virtual override returns (bool) { return accessServer.hasRoleForMe(role, account); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (role != ANY_ROLE) { accessServer.checkRoleForMe(role, account); } } /* ################################################################ * Owner management * ##############################################################*/ /** * @dev Returns the address of the current owner. */ function owner() public view virtual override returns (address) { return accessServer.getMyOwner(); } /** * Make another account the owner of this contract. * @param newOwner the new owner. * * Requirements: * * - Calling user MUST be owner. * - `newOwner` MUST NOT have the banned role. */ function transferOwnership(address newOwner) public virtual { address oldOwner = owner(); accessServer.setMyOwner(_msgSender(), newOwner); emit OwnershipTransferred(oldOwner, newOwner); } /* ################################################################ * Role Administration * ##############################################################*/ /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin( bytes32 role ) public view virtual override returns (bytes32) { return accessServer.getMyRoleAdmin(role); } /** * @dev Sets the admin role that controls a role. * * Requirements: * - caller MUST be the owner or have the admin role. */ function setRoleAdmin(bytes32 role, bytes32 adminRole) public virtual { accessServer.setRoleAdmin(_msgSender(), role, adminRole); } /* ################################################################ * Enumerating role members * ##############################################################*/ /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember( bytes32 role, uint256 index ) public view virtual override returns (address) { return accessServer.getMyRoleMember(role, index); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount( bytes32 role ) public view virtual override returns (uint256) { return accessServer.getMyRoleMemberCount(role); } /* ################################################################ * Granting / Revoking / Renouncing roles * ##############################################################*/ /** * Requirements: * * - Calling user MUST have the admin role * - If `role` is banned, calling user MUST be the owner * and `address` MUST NOT be the owner. * - If `role` is not banned, `account` MUST NOT be under sanctions. * * @inheritdoc IAccessControl */ function grantRole(bytes32 role, address account) public virtual override { if (!hasRole(role, account)) { accessServer.grantRole(_msgSender(), role, account); emit RoleGranted(role, account, _msgSender()); } } /** * Take the role away from the account. This will throw an exception * if you try to take the admin role (0x00) away from the owner. * * Requirements: * * - Calling user has admin role. * - If `role` is admin, `address` MUST NOT be owner. * - if `role` is banned, calling user MUST be owner. * * @inheritdoc IAccessControl */ function revokeRole(bytes32 role, address account) public virtual override { if (hasRole(role, account)) { accessServer.revokeRole(_msgSender(), role, account); emit RoleRevoked(role, account, _msgSender()); } } /** * Take a role away from yourself. This will throw an exception if you * are the contract owner and you are trying to renounce the admin role (0x00). * * Requirements: * * - if `role` is admin, calling user MUST NOT be owner. * - `account` is ignored. * - `role` MUST NOT be banned. * * @inheritdoc IAccessControl */ function renounceRole(bytes32 role, address) public virtual override { renounceRole(role); } /** * Take a role away from yourself. This will throw an exception if you * are the contract owner and you are trying to renounce the admin role (0x00). * * Requirements: * * - if `role` is admin, calling user MUST NOT be owner. * - `role` MUST NOT be banned. */ function renounceRole(bytes32 role) public virtual { accessServer.renounceRole(_msgSender(), role); emit RoleRevoked(role, _msgSender(), _msgSender()); // if (hasRole(role, _msgSender())) { // } } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "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); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; bytes32 constant DEFAULT_ADMIN = 0x00; bytes32 constant BANNED = "banned"; bytes32 constant MODERATOR = "moderator"; bytes32 constant ANY_ROLE = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; bytes32 constant BRIDGE_CONTRACT = keccak256("BRIDGE_CONTRACT"); bytes32 constant BRIDGE_ROLE_MGR = keccak256("BRIDGE_ROLE_MGR"); bytes32 constant CREATOR_ROLE_NAME = "creator"; bytes32 constant CUSTOMER_SERVICE = "Customer Service"; bytes32 constant MINTER_ROLE_NAME = "minter";
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "IAccessControlEnumerable.sol"; /** * @title ViciAccess Interface * @notice (c) 2023 ViciNFT https://vicinft.com/ * @author Josh Davis <[email protected]> * * @dev Interface for ViciAccess. * @dev External contracts SHOULD refer to implementers via this interface. */ interface IViciAccess is IAccessControlEnumerable { /** * @dev emitted when the owner changes. */ event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /** * @dev Revert if the address is on the OFAC sanctions list */ function enforceIsNotSanctioned(address account) external view; /** * @dev reverts if the account is banned or on the OFAC sanctions list. */ function enforceIsNotBanned(address account) external view; /** * @dev reverts if the account is not the owner and doesn't have the required role. */ function enforceOwnerOrRole(bytes32 role, address account) external view; /** * @dev returns true if the account is on the OFAC sanctions list. */ function isSanctioned(address account) external view returns (bool); /** * @dev returns true if the account is banned. */ function isBanned(address account) external view returns (bool); /** * @dev Returns the address of the current owner. */ function owner() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol) pragma solidity ^0.8.20; import {IAccessControl} from "IAccessControl.sol"; /** * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. */ interface IAccessControlEnumerable is IAccessControl { /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) external view returns (address); /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.6; interface ERC677ReceiverInterface { function onTokenTransfer( address sender, uint256 amount, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.24; import "MessageHashUtils.sol"; import "Initializable.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ * * @custom:storage-size 52 */ abstract contract EIP712 is Initializable { /* solhint-disable var-name-mixedcase */ bytes32 private _HASHED_NAME; bytes32 private _HASHED_VERSION; bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ function __EIP712_init(string memory name, string memory version) internal onlyInitializing { __EIP712_init_unchained(name, version); } function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash()); } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev The hash of the name parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712NameHash() internal virtual view returns (bytes32) { return _HASHED_NAME; } /** * @dev The hash of the version parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712VersionHash() internal virtual view returns (bytes32) { return _HASHED_VERSION; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; import {Strings} from "Strings.sol"; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "Math.sol"; import {SignedMath} from "SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // Copyright (c) 2021 the ethier authors (github.com/divergencetech/ethier) pragma solidity ^0.8.24; /** @notice Provides monotonic increasing and decreasing values, similar to OpenZeppelin's Counter but (a) limited in direction, and (b) allowing for steps > 1. */ library Monotonic { /** @notice Holds a value that can only increase. @dev The internal value MUST NOT be accessed directly. Instead use current() and add(). */ struct Increaser { uint256 value; } /// @notice Returns the current value of the Increaser. function current(Increaser storage incr) internal view returns (uint256) { return incr.value; } /// @notice Adds x to the Increaser's value. function add(Increaser storage incr, uint256 x) internal { incr.value += x; } /** @notice Holds a value that can only decrease. @dev The internal value MUST NOT be accessed directly. Instead use current() and subtract(). */ struct Decreaser { uint256 value; } /// @notice Returns the current value of the Decreaser. function current(Decreaser storage decr) internal view returns (uint256) { return decr.value; } /// @notice Subtracts x from the Decreaser's value. function subtract(Decreaser storage decr, uint256 x) internal { decr.value -= x; } struct Counter{ uint256 value; } function current(Counter storage _counter) internal view returns (uint256) { return _counter.value; } function add(Counter storage _augend, uint256 _addend) internal returns (uint256) { _augend.value += _addend; return _augend.value; } function subtract(Counter storage _minuend, uint256 _subtrahend) internal returns (uint256) { _minuend.value -= _subtrahend; return _minuend.value; } function increment(Counter storage _counter) internal returns (uint256) { return add(_counter, 1); } function decrement(Counter storage _counter) internal returns (uint256) { return subtract(_counter, 1); } function reset(Counter storage _counter) internal { _counter.value = 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "EnumerableSet.sol"; import "AddressUtils.sol"; import "IPluginIntrospection.sol"; import "ISimplePlugin.sol"; import "ISimplePluginExecutor.sol"; import "SimplePluginConstants.sol"; /** * @title Abstract Plugin Executor * @author Josh Davis * @notice Provides functionlity that any plugin executor would need. */ abstract contract AbstractPluginExecutor is ISimplePluginExecutor, IPluginIntrospection { using EnumerableSet for EnumerableSet.AddressSet; using AddressUtils for address; mapping(address => bool) public installedPlugins; /** * @dev key = selector, value is the set of plugins that validate the function. */ mapping(bytes4 => EnumerableSet.AddressSet) validators; /** * @dev key = selector, value is the set of plugins that post-validate the function. */ mapping(bytes4 => EnumerableSet.AddressSet) postops; /** * @dev key = selector, value is plugin that executes the function. */ mapping(bytes4 => address) executors; /** * @dev key = interfaceId, value is plugin that provides the implementation. */ mapping(bytes4 => address) public supportedInterfaces; function supportsInterface( bytes4 interfaceId ) public view virtual returns (bool) { return supportedInterfaces[interfaceId] != address(0) || interfaceId == type(IERC165).interfaceId || interfaceId == type(ISimplePluginExecutor).interfaceId; } /* ################################################################ * Modifiers * ##############################################################*/ /** * @notice make sure only authorized users are monkeying with your plugins */ modifier onlyPluginManager() { checkPluginManagerPermission(msg.sender); _; } /** * @notice for functions that can only be used as a callback from an installed plugin */ modifier onlyPlugin() { if (!installedPlugins[msg.sender]) { revert CallerIsNotPlugin(); } _; } /** * @notice for functions that cannot call into installed plugins */ modifier notToPlugin(address target) { if (installedPlugins[target]) { revert IllegalCallToPlugin(); } _; } /** * @notice makes it possible for public or external functions defined in your contact to be validated and * post-validated by a plugin. * @dev functions that use this SHOULD be external. */ modifier pluggable() { Message memory _msg = buildMessage(); _validate(_msg); _; _postExec(_msg); } /** * @notice makes it possible for private or internal functions defined in your contact to be validated and * post-validated by a plugin. * @param func the selector for the private or internal function */ modifier internalPluggable(bytes4 func) { Message memory _msg = buildMessage(); _msg.sig = func; _validate(_msg); _; _postExec(_msg); } /** * @notice subclasses MUST implement this to ensure only authorized users can add and remove plugins. */ function checkPluginManagerPermission(address caller) internal view virtual; /** * @notice sublclasses MAY implement this before allowing a plugin to have additional access to its functions. * See `executeFromPlugin` * @param plugin the plugin calling back into this contract * @param func the function it's trying to call */ function checkPluginInternalAccessAllowed( address plugin, bytes4 func ) internal view virtual {} /** * @notice sublclasses MAY implement this before allowing a plugin to cause this contract to make an external call. * @param plugin the plugin * @param target the contract it wants you to call * @param func the function it wants you to call * @param netValue the matic/ether/etc. it wants you to send */ function checkPluginExternalAccessAllowed( address plugin, address target, bytes4 func, uint256 netValue ) internal view virtual {} /* ################################################################ * Introspection * ##############################################################*/ /// @inheritdoc IPluginIntrospection function getFunctionInstrumentation( bytes4 func ) public view override returns (InstrumentedFunction memory) { return InstrumentedFunction( func, validators[func].values(), executors[func], postops[func].values() ); } /// @inheritdoc IPluginIntrospection function getValidators( bytes4 func ) public view override returns (address[] memory) { return validators[func].values(); } /// @inheritdoc IPluginIntrospection function getExectuor(bytes4 func) public view override returns (address) { return executors[func]; } /// @inheritdoc IPluginIntrospection function getPostops( bytes4 func ) public view override returns (address[] memory) { return postops[func].values(); } /* ################################################################ * Installation * ##############################################################*/ /** * @notice Uninstalls `oldPlugin`, then installs `newPlugin` * @param oldPlugin the plugin to be uninstalled * @param newPlugin the plugin to be installed * @dev see `installSimplePlugin()`, `uninstallSimplePlugin()` */ function replaceSimplePlugin( address oldPlugin, bytes calldata pluginUninstallData, address newPlugin, bytes calldata pluginInstallData, bool force ) public virtual override onlyPluginManager { _doPluginUninstall(oldPlugin, pluginUninstallData, force); _doPluginInstall(newPlugin, pluginInstallData); } /** * @notice installs a new plugin * @param plugin The address of the plugin to be installed * @dev emits SimplePluginInstalled * @dev reverts with PluginAlreadyInstalled if the plugin is already installed * @dev reverts with InvalidPlugin if the address does not implement ISimplePlugin * @dev reverts with ExecutePluginAlreadySet if there is already an execution plugin for the selector * * Requirements: * - Caller MUST have permission to install plugins * - Subclasses MAY add requirements by overriding `_doAdditionalInstallValidation()` */ function installSimplePlugin( address plugin, bytes calldata pluginInstallData ) public virtual override onlyPluginManager { _doPluginInstall(plugin, pluginInstallData); } function _doPluginInstall( address plugin, bytes calldata pluginInstallData ) internal { if (installedPlugins[plugin]) { revert PluginAlreadyInstalled(); } ISimplePlugin p = ISimplePlugin(plugin); if (!p.supportsInterface(type(ISimplePlugin).interfaceId)) { revert InvalidPlugin("Not ISimplePlugin"); } _doAdditionalInstallValidation(plugin); _setupInterfaces(p); _setupExecutes(p); _setupValidators(plugin, p.validates(), validators); _setupValidators(plugin, p.postExecs(), postops); installedPlugins[plugin] = true; p.onInstall(pluginInstallData); emit SimplePluginInstalled(plugin); } function _setupInterfaces(ISimplePlugin plugin) internal virtual { bytes4[] memory interfaceIds = plugin.providedInterfaces(); for (uint256 i = 0; i < interfaceIds.length; i++) { bytes4 interfaceId = interfaceIds[i]; if (supportedInterfaces[interfaceId] != address(0)) { revert ExecutePluginAlreadySet( interfaceId, supportedInterfaces[interfaceId] ); } supportedInterfaces[interfaceId] = address(plugin); } } function _setupExecutes(ISimplePlugin plugin) internal virtual { bytes4[] memory funcs = plugin.executes(); for (uint256 i = 0; i < funcs.length; i++) { bytes4 func = funcs[i]; if (executors[func] != address(0)) { revert ExecutePluginAlreadySet(func, executors[func]); } executors[func] = address(plugin); } } function _setupValidators( address plugin, bytes4[] memory funcs, mapping(bytes4 => EnumerableSet.AddressSet) storage plugins ) internal virtual { for (uint256 i = 0; i < funcs.length; i++) { plugins[funcs[i]].add(plugin); } } function _doAdditionalInstallValidation( address plugin ) internal view virtual {} /* ################################################################ * Uninstallation * ##############################################################*/ /** * @notice Uninstalls a plugin * @notice Uninstalling a plugin that defines an execute selector will cause calls to that function to fail. * @param plugin the plugin to be removed * @dev emits SimplePluginUninstalled * @dev reverts with PluginNotInstalled if the plugin is not installed * * Requirements: * - Caller MUST have permission to install plugins * - Subclasses MAY add requirements by overriding `_doAdditionalUninstallValidation()` */ function uninstallSimplePlugin( address plugin, bytes calldata pluginUninstallData ) public virtual override onlyPluginManager { _doPluginUninstall(plugin, pluginUninstallData, false); } function forceUninstallSimplePlugin( address plugin, bytes calldata pluginUninstallData ) public virtual override onlyPluginManager { _doPluginUninstall(plugin, pluginUninstallData, true); } function removePluginSelectorsAndInterfaces( address plugin, bytes4[] calldata interfaces, bytes4[] calldata selectors ) public virtual override onlyPluginManager { _teardownInterfaces(plugin, interfaces); _teardownExecutes(plugin, selectors); _teardownValidators(plugin, selectors, validators); _teardownValidators(plugin, selectors, postops); } function _doPluginUninstall( address plugin, bytes calldata pluginUninstallData, bool force ) internal { if (!installedPlugins[plugin]) { revert PluginNotInstalled(); } _doAdditionalUninstallValidation(plugin); ISimplePlugin p = ISimplePlugin(plugin); _teardownInterfaces(plugin, p.providedInterfaces()); _teardownExecutes(plugin, p.executes()); _teardownValidators(plugin, p.validates(), validators); _teardownValidators(plugin, p.postExecs(), postops); installedPlugins[plugin] = false; if (force) { p.onUninstall(pluginUninstallData); } else { try p.onUninstall(pluginUninstallData) {} catch Error( string memory reason ) { emit ErrorInPluginUninstall(bytes(reason)); } catch (bytes memory reason) { emit ErrorInPluginUninstall(reason); } } emit SimplePluginUninstalled(plugin); } function _teardownInterfaces( address plugin, bytes4[] memory interfaceIds ) internal virtual { for (uint256 i = 0; i < interfaceIds.length; i++) { if (supportedInterfaces[interfaceIds[i]] == plugin) supportedInterfaces[interfaceIds[i]] = address(0); } } function _teardownExecutes( address plugin, bytes4[] memory funcs ) internal virtual { for (uint256 i = 0; i < funcs.length; i++) { if (executors[funcs[i]] == plugin) executors[funcs[i]] = address(0); } } function _teardownValidators( address plugin, bytes4[] memory funcs, mapping(bytes4 => EnumerableSet.AddressSet) storage plugins ) internal virtual { for (uint256 i = 0; i < funcs.length; i++) { plugins[funcs[i]].remove(plugin); } } function _doAdditionalUninstallValidation( address plugin ) internal view virtual {} /* ################################################################ * Execution * ##############################################################*/ function buildMessage() internal virtual returns (Message memory) { return Message(msg.data, msg.sender, msg.sig, msg.value); } /** * @notice Execute a call from a plugin through the parent contract. * @dev Permissions must be granted to the calling plugin for the call to go through. * @param data The calldata to send to the parent contract. * @return result The return data from the call. * * Requirements: * - caller MUST be an installed plugin * - subclasses MAY add addtional requirements by overriding `checkPluginInternalAccessAllowed` */ function executeFromPlugin( bytes calldata data ) public payable virtual override onlyPlugin returns (bytes memory result) { checkPluginInternalAccessAllowed(msg.sender, msg.sig); result = address(this).functionCall(data); } /** * @notice Execute a call from a plugin to a non-plugin address. * @param target The address to be called. * @param value The value to send with the call. * @param data The calldata to send to the target. * @return The return data from the call. * * Requirements: * - caller MUST be an installed plugin * - `target` MUST NOT be an installed plugin * - subclasses MAY add addtional requirements by overriding `checkPluginExternalAccessAllowed` */ function executeFromPluginExternal( address target, uint256 value, bytes calldata data ) public payable virtual override onlyPlugin notToPlugin(target) returns (bytes memory) { bytes4 func = bytes4(data[:4]); uint256 netValue = (msg.value > value) ? msg.value - value : 0; checkPluginExternalAccessAllowed(msg.sender, target, func, netValue); return target.functionCallWithValue(data, value); } function _validate( Message memory _msg ) internal virtual returns (bytes memory result) { if (validators[_msg.sig].length() == 0) return TRUE; uint256 pluginCount = validators[_msg.sig].length(); for (uint256 i = 0; i < pluginCount; i++) { result = ISimplePlugin(validators[_msg.sig].at(i)).beforeHook(_msg); } } function _postExec( Message memory _msg ) internal virtual returns (bytes memory result) { if (postops[_msg.sig].length() == 0) return TRUE; uint256 pluginCount = postops[_msg.sig].length(); for (uint256 i = 0; i < pluginCount; i++) { result = ISimplePlugin(postops[_msg.sig].at(i)).afterHook(_msg); } } function _execute( Message memory _msg ) internal virtual returns (bytes memory) { return ISimplePlugin(executors[_msg.sig]).execute(_msg); } /** * @dev This is where the magic happens. * @dev If the first 4 bytes received are in the executors mapping, then that plugin's execute function is called. * @dev If it doesn't match anything, then it reverts with NoSuchMethodError */ fallback(bytes calldata) external payable returns (bytes memory result) { Message memory _msg = buildMessage(); if (executors[_msg.sig] == address(0)) revert NoSuchMethodError(); _validate(_msg); result = _execute(_msg); _postExec(_msg); } receive() external payable virtual {} /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[45] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; struct InstrumentedFunction { // The function selector bytes4 func; // The plugins that run before the function address[] validators; // The plugin that provides the function address executor; // The plugins that run after the function address[] postops; } interface IPluginIntrospection { /** * @notice returns information about installed plugins that provide or modify a function * @param func the function selector */ function getFunctionInstrumentation( bytes4 func ) external view returns (InstrumentedFunction memory); /** * @notice returns the addressess of installed plugins that run before a function * @param func the function selector */ function getValidators( bytes4 func ) external view returns (address[] memory); /** * @notice returns the address of the installed plugin that provides a function * @param func the function selector */ function getExectuor(bytes4 func) external view returns (address); /** * @notice returns the addressess of installed plugins that run after a function * @param func the function selector */ function getPostops(bytes4 func) external view returns (address[] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "IERC165.sol"; /** * @title Simple Plugin Interface * @author Josh Davis * @dev A plugin has three options for intercepting a function call: validation, execution, and post-validation. * @dev If a plugin validates a function, then the provided validation code runs before the function executes. * @dev If a plugin post-validates a function, then the provided validation code runs after the function executes. * @dev If a plugin executes a function, that means the plugin provides the implementation of the fuction. * @dev The selectors for the function calls a plugin will intercept are given by `validates()`, `executes()`, * and `postExecs()`. * @dev A Plugin Executor may have many plugins that validate or post validate a given function, but only one * that executes a function. * @dev Plugins may validate or post-validate functions provided by other plugins. * @dev If the function to be validated doesn't call `beforeHook()` or `postExec()`, then the plugin's * validation will not run. See AbstractPluginExecutor#pluggable modifier. * @dev If a function to be executed is already defined by the Plugin Executor, that verion will run and the * plugin version will be ignored. */ struct Message { bytes data; // original ABI-encoded function call address sender; // original message sender bytes4 sig; // function selector uint256 value; // amount of eth/matic sent with the transaction, if any } interface ISimplePlugin is IERC165 { /** * @notice called by the plugin executor when the plugin is installed * @param data implementation-specific data required to install and configure * the plugin */ function onInstall(bytes calldata data) external; /** * @notice called by the plugin executor when the plugin is uninstalled * @param data implementation-specific data required to cleanly remove the plugin */ function onUninstall(bytes calldata data) external; /** * @notice Returns the list of interface ids provided by this plugin. */ function providedInterfaces() external view returns (bytes4[] memory); /** * @notice Returns the selectors of the functions that this plugin will validate. */ function validates() external view returns (bytes4[] memory); /** * @notice Returns the selectors of the functions that this plugin will execute. */ function executes() external view returns (bytes4[] memory); /** * @notice Returns the selectors of the functions that this plugin will post validate. */ function postExecs() external view returns (bytes4[] memory); /** * @notice called by the plugin executor to validate a function * @param _msg the original message received by the Plugin Executor */ function beforeHook( Message calldata _msg ) external payable returns (bytes memory); /** * @notice called by the plugin executor to execute a function * @notice execute functions can only add new functions on the Plugin Executor. They * cannot replace existing functions. If the Plugin Executor has a function with the * same selector, the plugin version will never be called. * @param _msg the original message received by the Plugin Executor */ function execute( Message calldata _msg ) external payable returns (bytes memory); /** * @notice called by the plugin executor to post-validate a function * @param _msg the original message received by the Plugin Executor */ function afterHook( Message calldata _msg ) external payable returns (bytes memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "IERC165.sol"; import "ISimplePlugin.sol"; import "PluginErrorsAndEvents.sol"; /** * @title Plugin Executor Interface * @author Josh Davis * @notice For contracts that will use plugins */ interface ISimplePluginExecutor is PluginErrorsAndEvents, IERC165 { /** * @notice Installs a new plugin * @param plugin the plugin to be installed * @param pluginInstallData plugin-specific data required to install and configure * * Requirements: * - The plugin MUST NOT already be installed * - The plugin MUST NOT provide an execute selector already provided by an installed plugin * - Implementation MUST call plugin.onInstall() */ function installSimplePlugin( address plugin, bytes calldata pluginInstallData ) external; /** * @notice Removes a plugin * @param plugin the plugin to be removed * @param pluginUninstallData plugin-specific data required to clean uninstall * * Requirements: * - The plugin MUST be installed * - Implementation MUST call plugin.onUninstall() */ function uninstallSimplePlugin( address plugin, bytes calldata pluginUninstallData ) external; /** * @notice Removes a plugin without reverting if onUninstall() fails * @param plugin the plugin to be removed * @param pluginUninstallData plugin-specific data required to clean uninstall * * Requirements: * - The plugin MUST be installed * - Implementation MUST call plugin.onUninstall() */ function forceUninstallSimplePlugin( address plugin, bytes calldata pluginUninstallData ) external; /** * @notice remove the ability of a plugin to implement interfaces and respond to selectors * @param plugin the plugin to be removed * @param interfaces interface id support to be removed * @param selectors function support to be removed */ function removePluginSelectorsAndInterfaces( address plugin, bytes4[] calldata interfaces, bytes4[] calldata selectors ) external; /** * * @param oldPlugin the plugin to be removed * @param pluginUninstallData plugin-specific data required to clean uninstall * @param newPlugin the plugin to be installed * @param pluginInstallData plugin-specific data required to install and configure * @param force if true, will not revert if oldPlugin.onUninstall() reverts * * Requirements * - removing oldPlugin MUST meet all requirements for `uninstallSimplePlugin` * - installing newPlugin MUST meet all requirements for `installSimplePlugin` */ function replaceSimplePlugin( address oldPlugin, bytes calldata pluginUninstallData, address newPlugin, bytes calldata pluginInstallData, bool force ) external; /// @notice Execute a call from a plugin through the parent contract. /// @dev Permissions must be granted to the calling plugin for the call to go through. /// @param data The calldata to send to the parent contract. /// @return The return data from the call. function executeFromPlugin( bytes calldata data ) external payable returns (bytes memory); /// @notice Execute a call from a plugin to a non-plugin address. /// @dev If the target is a plugin, the call SHOULD revert. Permissions MUST be granted to the calling /// plugin for the call to go through. /// @param target The address to be called. /// @param value The value to send with the call. /// @param data The calldata to send to the target. /// @return The return data from the call. function executeFromPluginExternal( address target, uint256 value, bytes calldata data ) external payable returns (bytes memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; interface PluginErrorsAndEvents { event SimplePluginInstalled(address indexed plugin); event SimplePluginUninstalled(address indexed plugin); event ErrorInPluginUninstall(bytes reason); // @notice Revert if a function is called by something other than an ISimplePluginExecutor error InvalidPluginExecutor(address notExecutor); /// @notice Revert if a function called by something other than an installed plugin error CallerIsNotPlugin(); /// @notice Revert if a function is called by an installed plugin error IllegalCallByPlugin(); /// @notice Revert if a call is to an installed plugin error IllegalCallToPlugin(); /// @notice Revert if fallback can't find the function error NoSuchMethodError(); /// @notice Revert when installing a plugin that executes the same selector as an existing one error ExecutePluginAlreadySet(bytes4 func, address plugin); /// @notice Revert on install if the plugin has already been installed error PluginAlreadyInstalled(); /// @notice Revert on install if there is a problem with a plugin error InvalidPlugin(bytes32 reason); /// @notice Revert on uninstall error PluginNotInstalled(); /// @notice Revert if the calldata passed to onInstall/onUninstall is invalid error InvalidInitCode(bytes32 reason); /// @notice Revert if validation or execution fails due to bad call data error InvalidCallData(bytes4 selector); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; bytes constant FALSE = abi.encodePacked(uint256(0)); bytes constant TRUE = abi.encodePacked(uint256(1)); bytes constant BEFORE_HOOK_SELECTOR = "0x55cdfb83"; bytes constant AFTER_HOOK_SELECTOR = "0x495b0f93";
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "IERC20Metadata.sol"; import "IBridgeable.sol"; import "IViciAccess.sol"; import "ISimplePluginExecutor.sol"; import "IERC677.sol"; interface IModularViciERC20 is IERC20Metadata, IViciAccess, ISimplePluginExecutor, IBridgeable, IERC677 { function isMain() external returns (bool); function vault() external returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "AccessConstants.sol"; struct BridgeArgs { address caller; address fromAddress; address toAddress; uint256 remoteChainId; uint256 itemId; uint256 amount; } struct SendParams { address fromAddress; uint256 dstChainId; address toAddress; uint256 itemId; uint256 amount; } /** * @title Bridgeable Interface * @dev common interface for bridgeable tokens */ interface IBridgeable { event SentToBridge( address indexed fromAddress, address indexed toAddress, uint256 indexed itemId, uint256 amount, address caller, uint256 dstChainId ); event ReceivedFromBridge( address indexed fromAddress, address indexed toAddress, uint256 indexed itemId, uint256 amount, address caller, uint256 srcChainId ); /** * @dev Callback function to notify when tokens have been sent through a bridge. * @dev Implementations SHOULD either lock or burn these tokens. * @param args.caller the original message sender * @param args.fromAddress the owner of the tokens that were sent * @param args.toAddress the destination address on the other chain * @param args.remoteChainId the chain id for the destination * @param args.itemId the token id for ERC721 or ERC1155 tokens. Ignored for ERC20 tokens. * @param args.amount the amount of tokens sent for ERC20 and ERC1155 tokens. Ignored for ERC721 tokens. */ function sentToBridge(BridgeArgs calldata args) external payable; /** * @dev Callback function to notify when tokens have been sent through a bridge. * @dev Implementations SHOULD either unlock or mint these tokens and send them to the `toAddress`. * @dev IMPORTANT: access to this function MUST be tightly controlled. Otherwise it's an infinite free tokens function. * @param args.caller the original message sender * @param args.fromAddress the owner of the tokens that were sent * @param args.toAddress the destination address on this chain * @param args.srcChainId the chain id for the source * @param args.itemId the token id for ERC721 or ERC1155 tokens. Ignored for ERC20 tokens. * @param args.amount the amount of tokens sent for ERC20 and ERC1155 tokens. Ignored for ERC721 tokens. */ function receivedFromBridge(BridgeArgs calldata args) external payable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "IERC20Metadata.sol"; /** * @title IERC677 interface * @notice ERC677 extends ERC20 by adding the transfer and call function. */ interface IERC677 is IERC20Metadata { /** * @notice transfers `value` to `to` and calls `onTokenTransfer()`. * @param to the ERC677 Receiver * @param value the amount to transfer * @param data the abi encoded call data * * Requirements: * - `to` MUST implement ERC677ReceiverInterface. * - `value` MUST be sufficient to cover the receiving contract's fee. * - `data` MUST be the types expected by the receiving contract. * - caller MUST be a contract that implements the callback function * required by the receiving contract. * - this contract must represent a token that is accepted by the receiving * contract. */ function transferAndCall( address to, uint256 value, bytes memory data ) external returns (bool success); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "ISimplePluginExecutor.sol"; import "IOwnerOperator.sol"; import "IModularViciERC20.sol"; interface IModularERC20Ops is IOwnerOperator { /* ################################################################ * Queries * ##############################################################*/ function parent() external view returns (IModularViciERC20); /** * @dev Returns the total maximum possible that can be minted. */ function getMaxSupply() external view returns (uint256); /** * @dev Returns the amount that has been minted so far. */ function totalSupply() external view returns (uint256); /** * @dev returns the amount available to be minted. * @dev {total available} = {max supply} - {amount minted so far} */ function availableSupply() external view returns (uint256); /** * @dev see IERC20 */ function balanceOf(address account) external view returns (uint256 balance); /* ################################################################ * Minting / Burning / Transferring * ##############################################################*/ /** * @dev Safely mints a new token and transfers it to the specified address. * @dev Updates available quantities * * Requirements: * * - `mintData.operator` MUST be owner or have the required role. * - `mintData.operator` MUST NOT be banned. * - `mintData.toAddress` MUST NOT be 0x0. * - `mintData.toAddress` MUST NOT be banned. * - If `mintData.toAddress` refers to a smart contract, it must implement * {IERC20Receiver-onERC20Received}, which is called upon a safe * transfer. */ function mint(address operator, address toAddress, uint256 amount) external; /** * @dev see IERC20 */ function transfer( address operator, address fromAddress, address toAddress, uint256 amount ) external; /** * @dev Burns the identified token. * @dev Updates available quantities * * Requirements: * * - `burnData.operator` MUST be owner or have the required role. * - `burnData.operator` MUST NOT be banned. * - `burnData.operator` MUST own the token or be authorized by the * owner to transfer the token. */ function burn( address operator, address fromAddress, uint256 amount ) external; /* ################################################################ * Approvals / Allowances * ##############################################################*/ /** * @dev see IERC20 */ function allowance( address owner, address spender ) external view returns (uint256); /** * @dev See {IERC20Permit-permit}. */ function permit(address owner, address spender, uint256 amount) external; /** * @notice recover assets in banned or sanctioned accounts * * Requirements * - `operator` MUST be the contract owner. * - `fromAddress` MUST be banned or OFAC sanctioned * - `toAddress` MAY be the zero address, in which case the * assets are burned. * - `toAddress` MUST NOT be banned or OFAC sanctioned */ function recoverSanctionedAssets( address operator, address fromAddress, address toAddress ) external returns (uint256 amount); /* ################################################################ * Utility Coin Functions * ##############################################################*/ /** * @notice Transfers tokens from the caller to a recipient and establishes * a vesting schedule. * If `transferData.toAddress` already has a locked balance, then * - if `transferData.amount` is greater than the airdropThreshold AND `release` is later than the current * lockReleaseDate, the lockReleaseDate will be updated. * - if `transferData.amount` is less than the airdropThreshold OR `release` is earlier than the current * lockReleaseDate, the lockReleaseDate will be left unchanged. * param transferData describes the token transfer * @param release the new lock release date, as a Unix timestamp in seconds * * Requirements: * - caller MUST have the AIRDROPPER role * - the transaction MUST meet all requirements for a transfer * @dev see IERC20Operations.transfer */ function airdropTimelockedTokens( address operator, address toAddress, address fromAddress, uint256 amount, uint256 release ) external; /** * @notice Unlocks some or all of `account`'s locked tokens. * @param account the user * @param unlockAmount the amount to unlock * * Requirements: * - caller MUST be the owner or have the UNLOCK_LOCKED_TOKENS role * - `unlockAmount` MAY be greater than the locked balance, in which case * all of the account's locked tokens are unlocked. */ function unlockLockedTokens( address operator, address account, uint256 unlockAmount ) external; /** * @notice Resets the lock period for a batch of addresses * @notice This function has no effect on accounts without a locked token balance * @param release the new lock release date, as a Unix timestamp in seconds * @param addresses the list of addresses to be reset * * Requirements: * - caller MUST be the owner or have the UNLOCK_LOCKED_TOKENS role * - `release` MAY be zero or in the past, in which case the users' entire locked balances become unlocked * - `addresses` MAY contain accounts without a locked balance, in which case the account is unaffected */ function updateTimelocks( address operator, uint256 release, address[] calldata addresses ) external; /** * @notice Returns the amount of locked tokens for `account`. * @param account the user address */ function lockedBalanceOf(address account) external view returns (uint256); /** * @notice Returns the Unix timestamp when a user's locked tokens will be * released. * @param account the user address */ function lockReleaseDate(address account) external view returns (uint256); /** * @notice Returns the difference between `account`'s total balance and its * locked balance. * @param account the user address */ function unlockedBalanceOf(address account) external view returns (uint256); /** * @notice recovers tokens from lost wallets */ function recoverMisplacedTokens( address operator, address fromAddress, address toAddress ) external returns (uint256 amount); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; /** * @title Owner Operator Interface * @notice (c) 2023 ViciNFT https://vicinft.com/ * @author Josh Davis <[email protected]> * * @dev public interface for the Owner Operator contract */ interface IOwnerOperator { /** * @dev revert if the item does not exist */ function enforceItemExists(uint256 thing) external view; /* ################################################################ * Queries * ##############################################################*/ /** * @dev Returns whether `thing` exists. Things are created by transferring * from the null address, and things are destroyed by tranferring to * the null address. * @dev COINS: returns whether any have been minted and are not all burned. * * @param thing identifies the thing. * * Requirements: * - COINS: `thing` SHOULD be 1. */ function exists(uint256 thing) external view returns (bool); /** * @dev Returns the number of distict owners. * @dev use with `ownerAtIndex()` to iterate. */ function ownerCount() external view returns (uint256); /** * @dev Returns the address of the owner at the index. * @dev use with `ownerCount()` to iterate. * * @param index the index into the list of owners * * Requirements * - `index` MUST be less than the number of owners. */ function ownerAtIndex(uint256 index) external view returns (address); /** * @dev Returns the number of distict items. * @dev use with `itemAtIndex()` to iterate. * @dev COINS: returns 1 or 0 depending on whether any tokens exist. */ function itemCount() external view returns (uint256); /** * @dev Returns the ID of the item at the index. * @dev use with `itemCount()` to iterate. * @dev COINS: don't use this function. The ID is always 1. * * @param index the index into the list of items * * Requirements * - `index` MUST be less than the number of items. */ function itemAtIndex(uint256 index) external view returns (uint256); /** * @dev for a given item, returns the number that exist. * @dev NFTS: don't use this function. It returns 1 or 0 depending on * whether the item exists. Use `exists()` instead. */ function itemSupply(uint256 thing) external view returns (uint256); /** * @dev Returns how much of an item is held by an address. * @dev NFTS: Returns 0 or 1 depending on whether the address owns the item. * * @param owner the owner * @param thing identifies the item. * * Requirements: * - `owner` MUST NOT be the null address. * - `thing` MUST exist. */ function getBalance(address owner, uint256 thing) external view returns (uint256); /** * @dev Returns the list of distinct items held by an address. * @dev COINS: Don't use this function. * * @param user the user * * Requirements: * - `owner` MUST NOT be the null address. */ function userWallet(address user) external view returns (uint256[] memory); /** * @dev For a given address, returns the number of distinct items. * @dev Returns 0 if the address doesn't own anything here. * @dev use with `itemOfOwnerByIndex()` to iterate. * @dev COINS: don't use this function. It returns 1 or 0 depending on * whether the address has a balance. Use `balance()` instead. * * Requirements: * - `owner` MUST NOT be the null address. * - `thing` MUST exist. */ function ownerItemCount(address owner) external view returns (uint256); /** * @dev For a given address, returns the id of the item at the index. * @dev COINS: don't use this function. * * @param owner the owner. * @param index the index in the list of items. * * Requirements: * - `owner` MUST NOT be the null address. * - `index` MUST be less than the number of items. */ function itemOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev For a given item, returns the number of owners. * @dev use with `ownerOfItemAtIndex()` to iterate. * @dev COINS: don't use this function. Use `ownerCount()` instead. * @dev NFTS: don't use this function. If `thing` exists, the answer is 1. * * Requirements: * - `thing` MUST exist. */ function itemOwnerCount(uint256 thing) external view returns (uint256); /** * @dev For a given item, returns the owner at the index. * @dev use with `itemOwnerCount()` to iterate. * @dev COINS: don't use this function. Use `ownerAtIndex()` instead. * @dev NFTS: Returns the owner. * * @param thing identifies the item. * @param index the index in the list of owners. * * Requirements: * - `thing` MUST exist. * - `index` MUST be less than the number of owners. * - NFTS: `index` MUST be 0. */ function ownerOfItemAtIndex(uint256 thing, uint256 index) external view returns (address owner); /* ################################################################ * Minting / Burning / Transferring * ##############################################################*/ /** * @dev transfers an amount of thing from one address to another. * @dev if `fromAddress` is the null address, `amount` of `thing` is * created. * @dev if `toAddress` is the null address, `amount` of `thing` is * destroyed. * * @param operator the operator * @param fromAddress the current owner * @param toAddress the current owner * @param thing identifies the item. * @param amount the amount * * Requirements: * - NFTS: `amount` SHOULD be 1 * - COINS: `thing` SHOULD be 1 * - `fromAddress` and `toAddress` MUST NOT both be the null address * - `amount` MUST be greater than 0 * - if `fromAddress` is not the null address * - `amount` MUST NOT be greater than the current owner's balance * - `operator` MUST be approved */ function doTransfer( address operator, address fromAddress, address toAddress, uint256 thing, uint256 amount ) external; /* ################################################################ * Allowances / Approvals * ##############################################################*/ /** * @dev Reverts if `operator` is allowed to transfer `amount` of `thing` on * behalf of `fromAddress`. * @dev Reverts if `fromAddress` is not an owner of at least `amount` of * `thing`. * * @param operator the operator * @param fromAddress the owner * @param thing identifies the item. * @param amount the amount * * Requirements: * - NFTS: `amount` SHOULD be 1 * - COINS: `thing` SHOULD be 1 */ function enforceAccess( address operator, address fromAddress, uint256 thing, uint256 amount ) external view; /** * @dev Returns whether `operator` is allowed to transfer `amount` of * `thing` on behalf of `fromAddress`. * * @param operator the operator * @param fromAddress the owner * @param thing identifies the item. * @param amount the amount * * Requirements: * - NFTS: `amount` SHOULD be 1 * - COINS: `thing` SHOULD be 1 */ function isApproved( address operator, address fromAddress, uint256 thing, uint256 amount ) external view returns (bool); /** * @dev Returns whether an operator is approved for all items belonging to * an owner. * * @param fromAddress the owner * @param operator the operator */ function isApprovedForAll(address fromAddress, address operator) external view returns (bool); /** * @dev Toggles whether an operator is approved for all items belonging to * an owner. * * @param fromAddress the owner * @param operator the operator * @param approved the new approval status * * Requirements: * - `fromUser` MUST NOT be the null address * - `operator` MUST NOT be the null address * - `operator` MUST NOT be the `fromUser` */ function setApprovalForAll( address fromAddress, address operator, bool approved ) external; /** * @dev returns the approved allowance for an operator. * @dev NFTS: Don't use this function. Use `getApprovedForItem()` * * @param fromAddress the owner * @param operator the operator * @param thing identifies the item. * * Requirements: * - COINS: `thing` SHOULD be 1 */ function allowance( address fromAddress, address operator, uint256 thing ) external view returns (uint256); /** * @dev sets the approval amount for an operator. * @dev NFTS: Don't use this function. Use `approveForItem()` * * @param fromAddress the owner * @param operator the operator * @param thing identifies the item. * @param amount the allowance amount. * * Requirements: * - COINS: `thing` SHOULD be 1 * - `fromUser` MUST NOT be the null address * - `operator` MUST NOT be the null address * - `operator` MUST NOT be the `fromUser` */ function approve( address fromAddress, address operator, uint256 thing, uint256 amount ) external; /** * @dev Returns the address of the operator who is approved for an item. * @dev Returns the null address if there is no approved operator. * @dev COINS: Don't use this function. * * @param fromAddress the owner * @param thing identifies the item. * * Requirements: * - `thing` MUST exist */ function getApprovedForItem(address fromAddress, uint256 thing) external view returns (address); /** * @dev Approves `operator` to transfer `thing` to another account. * @dev COINS: Don't use this function. Use `setApprovalForAll()` or * `approve()` * * @param fromAddress the owner * @param operator the operator * @param thing identifies the item. * * Requirements: * - `fromUser` MUST NOT be the null address * - `operator` MAY be the null address * - `operator` MUST NOT be the `fromUser` * - `fromUser` MUST be an owner of `thing` */ function approveForItem( address fromAddress, address operator, uint256 thing ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "draft-IERC6093.sol"; bytes32 constant AIRDROP_ROLE_NAME = "airdrop"; bytes32 constant LOST_WALLET = keccak256("lost wallet"); bytes32 constant UNLOCK_LOCKED_TOKENS = keccak256("UNLOCK_LOCKED_TOKENS"); interface ViciERC20RolesErrorsEvents is IERC20Errors { /** * @notice revert when using lost wallet recovery on a wallet that is not lost. */ error InvalidLostWallet(address wallet); /** * @notice revert when using sanctioned asset recovery on a wallet that is not sanctioned. */ error InvalidSanctionedWallet(address wallet); /** * @notice revert when trying to mint beyond max supply */ error SoldOut(); /** * @notice emit when assets are recovered from a sanctioned wallet */ event SanctionedAssetsRecovered(address from, address to, uint256 value); /** * @notice emit when assets are recovered from a lost wallet */ event LostTokensRecovered(address from, address to, uint256 value); /** * @notice emit when a timelock is updated */ event LockUpdated( address indexed account, uint256 previousRelease, uint256 newRelease ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
{ "evmVersion": "istanbul", "optimizer": { "enabled": true, "runs": 200 }, "libraries": { "HybridViciERC20.sol": {} }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"CallerIsNotPlugin","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[{"internalType":"bytes4","name":"func","type":"bytes4"},{"internalType":"address","name":"plugin","type":"address"}],"name":"ExecutePluginAlreadySet","type":"error"},{"inputs":[],"name":"IllegalCallByPlugin","type":"error"},{"inputs":[],"name":"IllegalCallToPlugin","type":"error"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"InvalidCallData","type":"error"},{"inputs":[{"internalType":"bytes32","name":"reason","type":"bytes32"}],"name":"InvalidInitCode","type":"error"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"InvalidLostWallet","type":"error"},{"inputs":[{"internalType":"bytes32","name":"reason","type":"bytes32"}],"name":"InvalidPlugin","type":"error"},{"inputs":[{"internalType":"address","name":"notExecutor","type":"address"}],"name":"InvalidPluginExecutor","type":"error"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"InvalidSanctionedWallet","type":"error"},{"inputs":[],"name":"NoSuchMethodError","type":"error"},{"inputs":[],"name":"PluginAlreadyInstalled","type":"error"},{"inputs":[],"name":"PluginNotInstalled","type":"error"},{"inputs":[],"name":"SoldOut","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"reason","type":"bytes"}],"name":"ErrorInPluginUninstall","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousRelease","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRelease","type":"uint256"}],"name":"LockUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"LostTokensRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"itemId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"srcChainId","type":"uint256"}],"name":"ReceivedFromBridge","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"SanctionedAssetsRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"itemId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"dstChainId","type":"uint256"}],"name":"SentToBridge","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"plugin","type":"address"}],"name":"SimplePluginInstalled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"plugin","type":"address"}],"name":"SimplePluginUninstalled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"BANNED_ROLE_NAME","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MODERATOR_ROLE_NAME","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accessServer","outputs":[{"internalType":"contract IAccessServer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"availableSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"circulatingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"enforceIsNotBanned","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"enforceIsNotSanctioned","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"enforceOwnerOrRole","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"executeFromPlugin","outputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"executeFromPluginExternal","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"plugin","type":"address"},{"internalType":"bytes","name":"pluginUninstallData","type":"bytes"}],"name":"forceUninstallSimplePlugin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"func","type":"bytes4"}],"name":"getExectuor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"func","type":"bytes4"}],"name":"getFunctionInstrumentation","outputs":[{"components":[{"internalType":"bytes4","name":"func","type":"bytes4"},{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"address[]","name":"postops","type":"address[]"}],"internalType":"struct InstrumentedFunction","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getOwnerAtIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwnerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"func","type":"bytes4"}],"name":"getPostops","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"func","type":"bytes4"}],"name":"getValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IAccessServer","name":"_accessServer","type":"address"},{"internalType":"contract IModularERC20Ops","name":"_tokenData","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"},{"internalType":"bool","name":"_isMain","type":"bool"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"plugin","type":"address"},{"internalType":"bytes","name":"pluginInstallData","type":"bytes"}],"name":"installSimplePlugin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"installedPlugins","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isBanned","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMain","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isSanctioned","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockReleaseDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockedBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"fromAddress","type":"address"},{"internalType":"address","name":"toAddress","type":"address"},{"internalType":"uint256","name":"remoteChainId","type":"uint256"},{"internalType":"uint256","name":"itemId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct BridgeArgs","name":"args","type":"tuple"}],"name":"receivedFromBridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isMain","type":"bool"}],"name":"reinit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"plugin","type":"address"},{"internalType":"bytes4[]","name":"interfaces","type":"bytes4[]"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"name":"removePluginSelectorsAndInterfaces","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"oldPlugin","type":"address"},{"internalType":"bytes","name":"pluginUninstallData","type":"bytes"},{"internalType":"address","name":"newPlugin","type":"address"},{"internalType":"bytes","name":"pluginInstallData","type":"bytes"},{"internalType":"bool","name":"force","type":"bool"}],"name":"replaceSimplePlugin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"fromAddress","type":"address"},{"internalType":"address","name":"toAddress","type":"address"},{"internalType":"uint256","name":"remoteChainId","type":"uint256"},{"internalType":"uint256","name":"itemId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct BridgeArgs","name":"args","type":"tuple"}],"name":"sentToBridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"bytes32","name":"adminRole","type":"bytes32"}],"name":"setRoleAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"supportedInterfaces","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenData","outputs":[{"internalType":"contract IModularERC20Ops","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"toAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"transferAndCall","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"fromAddress","type":"address"},{"internalType":"address","name":"toAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"plugin","type":"address"},{"internalType":"bytes","name":"pluginUninstallData","type":"bytes"}],"name":"uninstallSimplePlugin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"unlockedBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"toAddress","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"toAddress","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"contract IERC1155","name":"tokenContract","type":"address"}],"name":"withdrawERC1155","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"toAddress","type":"address"},{"internalType":"contract IERC20","name":"tokenContract","type":"address"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address payable","name":"toAddress","type":"address"},{"internalType":"contract IERC721","name":"tokenContract","type":"address"}],"name":"withdrawERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b615dc780620000f36000396000f3fe6080604052600436106104095760003560e01c80638387aa0411610213578063a8aa987a11610123578063d91eff61116100ab578063ef18374a1161007a578063ef18374a14610c9c578063f1e152df14610cb1578063f2fde38b14610cd1578063fbfa77cf14610cf1578063fe523e1914610d1257610410565b8063d91eff6114610c29578063dd62ed3e14610c49578063df592f7d14610c69578063ec27e0b714610c8957610410565b8063c6288f35116100f2578063c6288f3514610b94578063ca15c87314610bb4578063d505accf14610bd4578063d547741f14610bf4578063d5abeb0114610c1457610410565b8063a8aa987a14610b14578063a9059cbb14610b34578063b37f3a2414610b54578063bee547e114610b7457610410565b80639358928b116101a6578063a217fddf11610175578063a217fddf14610a8c578063a24a517d14610aa1578063a50fdd5514610ac1578063a58b409b14610ae1578063a7a2bba414610af457610410565b80639358928b14610a2f57806394ed11e714610a4457806395d89b4114610a5757806397f735d514610a6c57610410565b80638da5cb5b116101e25780638da5cb5b146109ba5780639010d07c146109cf57806391d14854146109ef57806392e3a3e214610a0f57610410565b80638387aa04146109455780638456cb591461096557806384955c881461097a5780638bb9c5bf1461099a57610410565b806336568abe1161031957806351cff8d9116102a15780635d29dab4116102705780635d29dab4146108ae578063604269d1146108ce57806370a08231146108f05780637ecc2b56146109105780637ecebe001461092557610410565b806351cff8d91461082957806357b22d2d1461084957806359355736146108765780635c975abb1461089657610410565b80634000aea0116102e85780634000aea01461076857806340910fd91461078857806343a68ae5146107a857806344aba123146107c85780634842ce511461080957610410565b806336568abe1461070057806338997b11146107205780633c6182ef146107335780633f4ba83a1461075357610410565b806323b872dd1161039c578063313ce5671161036b578063313ce5671461066e57806332e7a3cb1461069b5780633408e470146106b857806336034372146106cb5780633644e515146106eb57610410565b806323b872dd146105ee578063248a9ca31461060e57806326bdf1211461062e5780632f2ff15d1461064e57610410565b80631584ba38116103d85780631584ba381461054557806318160ddd1461057c5780631d1891df1461059f5780631e4e0091146105cc57610410565b806301ffc9a714610490578063024fd650146104c557806306fdde0314610503578063095ea7b31461052557610410565b3661041057005b6000366060600061041f610d43565b6040808201516001600160e01b031916600090815261013160205220549091506001600160a01b031661046557604051631661b6e560e11b815260040160405180910390fd5b61046e81610dcd565b5061047881610efc565b915061048381610f95565b5050915050805190602001f35b34801561049c57600080fd5b506104b06104ab366004614d77565b6110ab565b60405190151581526020015b60405180910390f35b3480156104d157600080fd5b50610101546104eb9061010090046001600160a01b031681565b6040516001600160a01b0390911681526020016104bc565b34801561050f57600080fd5b506105186110e5565b6040516104bc9190614de4565b34801561053157600080fd5b506104b0610540366004614e0c565b611173565b34801561055157600080fd5b506104eb610560366004614d77565b610132602052600090815260409020546001600160a01b031681565b34801561058857600080fd5b506105916111a8565b6040519081526020016104bc565b3480156105ab57600080fd5b506105bf6105ba366004614d77565b611227565b6040516104bc9190614e7d565b3480156105d857600080fd5b506105ec6105e7366004614ee8565b6112cc565b005b3480156105fa57600080fd5b506104b0610609366004614f0a565b611349565b34801561061a57600080fd5b50610591610629366004614f4b565b611380565b34801561063a57600080fd5b506104eb610649366004614f4b565b6113ef565b34801561065a57600080fd5b506105ec610669366004614f64565b611463565b34801561067a57600080fd5b50610101546106899060ff1681565b60405160ff90911681526020016104bc565b3480156106a757600080fd5b506105916518985b9b995960d21b81565b3480156106c457600080fd5b5046610591565b3480156106d757600080fd5b506105ec6106e6366004614fdf565b611537565b3480156106f757600080fd5b50610591611643565b34801561070c57600080fd5b506105ec61071b366004614f64565b61164d565b61051861072e3660046150a2565b611656565b34801561073f57600080fd5b506105ec61074e3660046150fd565b611754565b34801561075f57600080fd5b506105ec6117cb565b34801561077457600080fd5b506104b06107833660046150a2565b61183e565b34801561079457600080fd5b506105ec6107a336600461519c565b6118dc565b3480156107b457600080fd5b506105ec6107c3366004615255565b611993565b3480156107d457600080fd5b506104eb6107e3366004614d77565b6001600160e01b031916600090815261013160205260409020546001600160a01b031690565b34801561081557600080fd5b506105ec610824366004615255565b6119ae565b34801561083557600080fd5b506105ec6108443660046152a9565b6119c2565b34801561085557600080fd5b50610869610864366004614d77565b611a37565b6040516104bc91906152c6565b34801561088257600080fd5b506105916108913660046152a9565b611a5d565b3480156108a257600080fd5b5060655460ff166104b0565b3480156108ba57600080fd5b506105ec6108c93660046152d9565b611a96565b3480156108da57600080fd5b50610101546104b090600160a81b900460ff1681565b3480156108fc57600080fd5b5061059161090b3660046152a9565b611b0a565b34801561091c57600080fd5b50610591611b43565b34801561093157600080fd5b506105916109403660046152a9565b611b99565b34801561095157600080fd5b506105ec6109603660046152a9565b611bb7565b34801561097157600080fd5b506105ec611c11565b34801561098657600080fd5b506105916109953660046152a9565b611c82565b3480156109a657600080fd5b506105ec6109b5366004614f4b565b611cbb565b3480156109c657600080fd5b506104eb611d77565b3480156109db57600080fd5b506104eb6109ea366004614ee8565b611de5565b3480156109fb57600080fd5b506104b0610a0a366004614f64565b611e61565b348015610a1b57600080fd5b506105ec610a2a36600461531b565b611ed7565b348015610a3b57600080fd5b50610591611f77565b610518610a52366004615338565b611fbd565b348015610a6357600080fd5b50610518612780565b348015610a7857600080fd5b506104b0610a873660046152a9565b61278e565b348015610a9857600080fd5b50610591600081565b348015610aad57600080fd5b506105ec610abc3660046152a9565b6127fe565b348015610acd57600080fd5b506033546104eb906001600160a01b031681565b6105ec610aef366004615379565b612830565b348015610b0057600080fd5b506105ec610b0f366004614f64565b612972565b348015610b2057600080fd5b506105ec610b2f3660046152d9565b61299c565b348015610b4057600080fd5b506104b0610b4f366004614e0c565b612a10565b348015610b6057600080fd5b506105ec610b6f36600461538b565b612a33565b348015610b8057600080fd5b506105ec610b8f366004615255565b612a5c565b348015610ba057600080fd5b50610869610baf366004614d77565b612a72565b348015610bc057600080fd5b50610591610bcf366004614f4b565b612a98565b348015610be057600080fd5b506105ec610bef366004615435565b612aca565b348015610c0057600080fd5b506105ec610c0f366004614f64565b612c50565b348015610c2057600080fd5b50610591612d24565b348015610c3557600080fd5b506105916836b7b232b930ba37b960b91b81565b348015610c5557600080fd5b50610591610c643660046154a3565b612d7a565b348015610c7557600080fd5b506104b0610c843660046152a9565b612df7565b6105ec610c97366004615379565b612e2a565b348015610ca857600080fd5b50610591612f4e565b348015610cbd57600080fd5b50610591610ccc3660046152a9565b612fa4565b348015610cdd57600080fd5b506105ec610cec3660046152a9565b612fdd565b348015610cfd57600080fd5b50610102546104eb906001600160a01b031681565b348015610d1e57600080fd5b506104b0610d2d3660046152a9565b61012e6020526000908152604090205460ff1681565b60408051608081018252606080825260006020830181905292820183905281019190915260405180608001604052806000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250938552505033602084015250356001600160e01b031916604082015234606090910152919050565b6040808201516001600160e01b031916600090815261012f60205220606090610df590613099565b600003610e1f576040805160016020820152015b6040516020818303038152906040529050919050565b6040808301516001600160e01b031916600090815261012f602052908120610e4690613099565b905060005b81811015610ef5576040808501516001600160e01b031916600090815261012f60205220610e7990826130a3565b6001600160a01b031663d980b8d9856040518263ffffffff1660e01b8152600401610ea491906154d1565b6000604051808303816000875af1158015610ec3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610eeb919081019061556a565b9250600101610e4b565b5050919050565b6040808201516001600160e01b0319166000908152610131602052819020549051639099c17560e01b81526060916001600160a01b031690639099c17590610f489085906004016154d1565b6000604051808303816000875af1158015610f67573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f8f919081019061556a565b92915050565b6040808201516001600160e01b031916600090815261013060205220606090610fbd90613099565b600003610fd557604080516001602082015201610e09565b6040808301516001600160e01b0319166000908152610130602052908120610ffc90613099565b905060005b81811015610ef5576040808501516001600160e01b03191660009081526101306020522061102f90826130a3565b6001600160a01b03166352b4392c856040518263ffffffff1660e01b815260040161105a91906154d1565b6000604051808303816000875af1158015611079573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110a1919081019061556a565b9250600101611001565b60006110b6826130af565b806110c557506110c5826130ff565b80610f8f57506001600160e01b03198216634ddc0f0f60e11b1492915050565b60ff80546110f290615601565b80601f016020809104026020016040519081016040528092919081815260200182805461111e90615601565b801561116b5780601f106111405761010080835404028352916020019161116b565b820191906000526020600020905b81548152906001019060200180831161114e57829003601f168201915b505050505081565b60008061117e610d43565b905061118981610dcd565b50611195338585613160565b91506111a081610f95565b505092915050565b600061010160019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112229190615635565b905090565b6040805160808101825260008082526060602083018190529282015281810191909152604080516080810182526001600160e01b03198416808252600090815261012f6020908152929020909182019061128090613224565b81526001600160e01b03198416600081815261013160209081526040808320546001600160a01b03168286015292825261013090528190209101906112c490613224565b905292915050565b6033546001600160a01b0316630997ce71336040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526024810185905260448101849052606401600060405180830381600087803b15801561132d57600080fd5b505af1158015611341573d6000803e3d6000fd5b505050505050565b600080611354610d43565b905061135f81610dcd565b5061136c33868686613231565b915061137781610f95565b50509392505050565b603354604051632b25c9c760e01b8152600481018390526000916001600160a01b031690632b25c9c7906024015b602060405180830381865afa1580156113cb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8f9190615635565b61010154604051638ea6902960e01b81526004810183905260009161010090046001600160a01b031690638ea6902990602401602060405180830381865afa15801561143f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8f919061564e565b61146d8282611e61565b611533576033546001600160a01b0316633290f93a336040516001600160e01b031960e084901b1681526001600160a01b039182166004820152602481018690529084166044820152606401600060405180830381600087803b1580156114d357600080fd5b505af11580156114e7573d6000803e3d6000fd5b505050506114f23390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b611540336132c5565b61157d858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132f792505050565b6115ba858383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506133c792505050565b6115fb8583838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061012f9250613497915050565b61163c858383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506101309250613497915050565b5050505050565b6000611222613503565b61153382611cbb565b33600090815261012e602052604090205460609060ff1661168a5760405163028b1dd160e41b815260040160405180910390fd5b6001600160a01b038516600090815261012e6020526040902054859060ff16156116c75760405163040846c960e11b815260040160405180910390fd5b60006116d6600482868861566b565b6116df91615695565b905060008634116116f15760006116fb565b6116fb87346156d9565b905061174886868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050506001600160a01b038b169190508961357e565b98975050505050505050565b6033546001600160a01b031663765e9fa6336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160006040518083038186803b1580156117a557600080fd5b505afa1580156117b9573d6000803e3d6000fd5b505050506113418686868686866135a4565b6033546001600160a01b031663765e9fa6336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160006040518083038186803b15801561181c57600080fd5b505afa158015611830573d6000803e3d6000fd5b5050505061183c613614565b565b600080611849610d43565b905061185481610dcd565b5061186133338888613231565b9150856001600160a01b03811663a4c0ed36338888886040518563ffffffff1660e01b81526004016118969493929190615715565b600060405180830381600087803b1580156118b057600080fd5b505af11580156118c4573d6000803e3d6000fd5b50505050506118d281610f95565b5050949350505050565b600054600290610100900460ff161580156118fe575060005460ff8083169116105b6119235760405162461bcd60e51b815260040161191a90615747565b60405180910390fd5b6000805461ffff191660ff8316176101001790556119478989898989898989613666565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050505050505050565b61199c336132c5565b6119a98383836001613707565b505050565b6119b7336132c5565b6119a9838383613af1565b6033546001600160a01b031663765e9fa6336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160006040518083038186803b158015611a1357600080fd5b505afa158015611a27573d6000803e3d6000fd5b50505050611a3481613d83565b50565b6001600160e01b03198116600090815261012f60205260409020606090610f8f90613224565b61010154604051632c9aab9b60e11b81526001600160a01b038381166004830152600092610100900416906359355736906024016113ae565b6033546001600160a01b031663765e9fa6336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160006040518083038186803b158015611ae757600080fd5b505afa158015611afb573d6000803e3d6000fd5b505050506119a9838383613db8565b610101546040516370a0823160e01b81526001600160a01b038381166004830152600092610100900416906370a08231906024016113ae565b600061010160019054906101000a90046001600160a01b03166001600160a01b0316637ecc2b566040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111fe573d6000803e3d6000fd5b6001600160a01b038116600090815260fe6020526040812054610f8f565b6033546040516320e1ea8160e21b81526001600160a01b03838116600483015290911690638387aa04906024015b60006040518083038186803b158015611bfd57600080fd5b505afa15801561163c573d6000803e3d6000fd5b6033546001600160a01b031663765e9fa6336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160006040518083038186803b158015611c6257600080fd5b505afa158015611c76573d6000803e3d6000fd5b5050505061183c613e2b565b61010154604051631092ab9160e31b81526001600160a01b038381166004830152600092610100900416906384955c88906024016113ae565b6033546001600160a01b031663f3c3437d336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b158015611d1557600080fd5b505af1158015611d29573d6000803e3d6000fd5b50505050611d343390565b6001600160a01b0316336001600160a01b0316827ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a450565b6033546040805163208f1f9960e01b815290516000926001600160a01b03169163208f1f999160048083019260209291908290030181865afa158015611dc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611222919061564e565b6033546040516338c43adf60e11b815260048101849052602481018390526000916001600160a01b03169063718875be90604401602060405180830381865afa158015611e36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e5a919061564e565b9392505050565b603354604051635219898160e11b8152600481018490526001600160a01b038381166024830152600092169063a433130290604401602060405180830381865afa158015611eb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e5a9190615795565b600054600290610100900460ff16158015611ef9575060005460ff8083169116105b611f155760405162461bcd60e51b815260040161191a90615747565b6000805461ffff191660ff831617610100179055611f3282613e68565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b61010154600090600160a81b900460ff1615611fb55761010254611fa3906001600160a01b0316611b0a565b611fab6111a8565b61122291906156d9565b6112226111a8565b33600090815261012e602052604090205460609060ff16611ff15760405163028b1dd160e41b815260040160405180910390fd5b6004821115612776576000612009600482858761566b565b61201291615695565b905063039cbf0d60e21b6001600160e01b03198216016120cf576084831461204f57806040516313efbce360e31b815260040161191a91906157b2565b6000808080612061876004818b61566b565b81019061206e91906157c7565b935093509350935061208284848484613231565b6120a6576040805160006020820152016040516020818303038152906040526120c3565b6040805160016020820152015b6040516020818303038152906040525b95505050505050610f8f565b631c9e220d60e11b6001600160e01b0319821601612185576064831461210a57806040516313efbce360e31b815260040161191a91906157b2565b6000808061211b866004818a61566b565b8101906121289190614f0a565b925092509250612139838383613ee4565b61215d5760408051600060208201520160405160208183030381529060405261217a565b6040805160016020820152015b6040516020818303038152906040525b945050505050610f8f565b630251bb9160e21b6001600160e01b03198216016121ef57606483146121c057806040516313efbce360e31b815260040161191a91906157b2565b600080806121d1866004818a61566b565b8101906121de9190614f0a565b925092509250612139838383613f65565b6339e6e22f60e21b6001600160e01b0319821601612259576064831461222a57806040516313efbce360e31b815260040161191a91906157b2565b6000808061223b866004818a61566b565b8101906122489190614f0a565b925092509250612139838383613160565b63540861fb60e11b6001600160e01b031982160161239c576064831461229457806040516313efbce360e31b815260040161191a91906157b2565b600080806122a5866004818a61566b565b8101906122b29190615818565b61010154604051632bf79e0560e11b81526001600160a01b0380861660048301528085166024830152808416604483015294975092955090935060009261010090910416906357ef3c0a906064016020604051808303816000875af115801561231f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123439190615635565b90507fb6153b6bd7894806f48017bc32f1de542ca0b4b97bf5dd9a43ec5c52fabd21a883838360405161237893929190615848565b60405180910390a161238b838383613fdc565b6040805160208101839052016120b3565b6338cec1f160e21b6001600160e01b03198216016124bb5760a483146123d757806040516313efbce360e31b815260040161191a91906157b2565b6000808080806123ea886004818c61566b565b8101906123f7919061586c565b610101546040516307313e0f60e21b81526001600160a01b038088166004830152808716602483015280861660448301526064820185905260848201849052969b509499509297509095509350610100900490911690631cc4f83c9060a401600060405180830381600087803b15801561247057600080fd5b505af1158015612484573d6000803e3d6000fd5b50505050612493848484613fdc565b6040805160016020820152016040516020818303038152906040529650505050505050610f8f565b63f3f9e74b60e01b6001600160e01b031982160161259a57606483146124f657806040516313efbce360e31b815260040161191a91906157b2565b60008080612507866004818a61566b565b8101906125149190614f0a565b61010154604051630c0618b560e01b8152939650919450925061010090046001600160a01b031690630c0618b59061255490869086908690600401615848565b600060405180830381600087803b15801561256e57600080fd5b505af1158015612582573d6000803e3d6000fd5b50505050600160405160200161216a91815260200190565b63064e9c1560e41b6001600160e01b03198216016126555760a4831080156125d7575060206125ca6004856156d9565b6125d491906158c7565b15155b156125f757806040516313efbce360e31b815260040161191a91906157b2565b60008080612608866004818a61566b565b810190612615919061590c565b610101546040516309b163eb60e41b8152939650919450925061010090046001600160a01b031690639b163eb090612554908690869086906004016159ce565b63a2e5b8b160e01b6001600160e01b0319821601612774576064831461269057806040516313efbce360e31b815260040161191a91906157b2565b600080806126a1866004818a61566b565b8101906126ae9190615818565b61010154604051635d1a474f60e01b81526001600160a01b038086166004830152808516602483015280841660448301529497509295509093506000926101009091041690635d1a474f906064016020604051808303816000875af115801561271b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273f9190615635565b90507f2283dd8f0aa4512bb878b51898d84e80c33b3620cba1edaad7f13e555e097c9c83838360405161237893929190615848565b505b611e5a838361402e565b61010080546110f290615601565b60335460405163b924698760e01b81526001600160a01b038381166004830152600092169063b9246987906024015b602060405180830381865afa1580156127da573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8f9190615795565b6033546040516389c75e1160e01b81526001600160a01b038381166004830152909116906389c75e1190602401611be5565b600061283a610d43565b905061284581610dcd565b507f3fd4a614bd02c8fb908a3b3a05852476cf4c63cfc1b7280860fd956aa0982f9f61287181336140a4565b61010154600160a81b900460ff16156128b657610102546128b0906001600160a01b0316806128a660608701604088016152a9565b8660a00135613231565b506128d6565b6128d4336128ca60608601604087016152a9565b8560a00135613ee4565b505b60016128e860608501604086016152a9565b6001600160a01b031661290160408601602087016152a9565b6001600160a01b03167ff4ea29784a8ad7456fb8ea0b9af463d31bde69edb825d92a73ca63096227b76d60a087013561293d60208901896152a9565b604080519283526001600160a01b03919091166020830152606089810135838301529051918290030190a4506119a981610f95565b61297a611d77565b6001600160a01b0316816001600160a01b0316146115335761153382826140a4565b6033546001600160a01b031663765e9fa6336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160006040518083038186803b1580156129ed57600080fd5b505afa158015612a01573d6000803e3d6000fd5b505050506119a983838361410d565b600080612a1b610d43565b9050612a2681610dcd565b5061119533338686613231565b612a3c336132c5565b612a4887878784613707565b612a53848484613af1565b50505050505050565b612a65336132c5565b6119a98383836000613707565b6001600160e01b03198116600090815261013060205260409020606090610f8f90613224565b60335460405163bdb44f2960e01b8152600481018390526000916001600160a01b03169063bdb44f29906024016113ae565b6000612ad4610d43565b9050612adf81610dcd565b5084421115612b305760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015260640161191a565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9898989612b5f8d61416b565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e0016040516020818303038152906040528051906020012090506000612bba82614197565b90506000612bca828888886141c4565b90508a6001600160a01b0316816001600160a01b031614612c2d5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015260640161191a565b612c388b8b8b613160565b50505050612c4581610f95565b505050505050505050565b612c5a8282611e61565b15611533576033546001600160a01b0316638c63a1a1336040516001600160e01b031960e084901b1681526001600160a01b039182166004820152602481018690529084166044820152606401600060405180830381600087803b158015612cc157600080fd5b505af1158015612cd5573d6000803e3d6000fd5b50505050612ce03390565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600061010160019054906101000a90046001600160a01b03166001600160a01b0316634c0f38c26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111fe573d6000803e3d6000fd5b61010154604051636eb1769f60e11b81526001600160a01b03848116600483015283811660248301526000926101009004169063dd62ed3e90604401602060405180830381865afa158015612dd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e5a9190615635565b60335460405163df592f7d60e01b81526001600160a01b038381166004830152600092169063df592f7d906024016127bd565b6000612e34610d43565b9050612e3f81610dcd565b507f3fd4a614bd02c8fb908a3b3a05852476cf4c63cfc1b7280860fd956aa0982f9f612e6b81336140a4565b61010154600160a81b900460ff1615612ebb57612eb5612e8e60208501856152a9565b612e9e60408601602087016152a9565b610102546001600160a01b031660a0870135613231565b50612ee7565b612ee5612ecb60208501856152a9565b612edb60408601602087016152a9565b8560a00135613f65565b505b6001612ef960608501604086016152a9565b6001600160a01b0316612f1260408601602087016152a9565b6001600160a01b03167f49e86899b41934ffa93d6db47f37670313228803b4c819af30cd42637d84096a60a087013561293d60208901896152a9565b600061010160019054906101000a90046001600160a01b03166001600160a01b0316630db026226040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111fe573d6000803e3d6000fd5b6101015460405163f1e152df60e01b81526001600160a01b0383811660048301526000926101009004169063f1e152df906024016113ae565b6000612fe7611d77565b6033549091506001600160a01b0316634001303f336040516001600160e01b031960e084901b1681526001600160a01b0391821660048201529085166024820152604401600060405180830381600087803b15801561304557600080fd5b505af1158015613059573d6000803e3d6000fd5b50506040516001600160a01b038086169350841691507f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000610f8f825490565b6000611e5a83836141f2565b60006001600160e01b03198216637965db0b60e01b14806130e057506001600160e01b03198216635a05180f60e01b145b80610f8f57506301ffc9a760e01b6001600160e01b0319831614610f8f565b6001600160e01b03198116600090815261013260205260408120546001600160a01b031615158061314057506001600160e01b031982166301ffc9a760e01b145b80610f8f57506001600160e01b03198216639c0910f560e01b1492915050565b610101546040516306191dd160e21b815260009161010090046001600160a01b03169063186477449061319b90879087908790600401615848565b600060405180830381600087803b1580156131b557600080fd5b505af11580156131c9573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161321291815260200190565b60405180910390a35060019392505050565b60606000611e5a8361421c565b61010154604051633c6340f360e21b81526001600160a01b03868116600483015285811660248301528481166044830152606482018490526000926101009004169063f18d03cc90608401600060405180830381600087803b15801561329657600080fd5b505af11580156132aa573d6000803e3d6000fd5b505050506132b9848484613fdc565b5060015b949350505050565b603354604051633b2f4fd360e11b81526001600160a01b0383811660048301529091169063765e9fa690602401611be5565b60005b81518110156119a957826001600160a01b03166101326000848481518110613324576133246159f5565b6020908102919091018101516001600160e01b0319168252810191909152604001600020546001600160a01b0316036133bf5760006101326000848481518110613370576133706159f5565b60200260200101516001600160e01b0319166001600160e01b031916815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b6001016132fa565b60005b81518110156119a957826001600160a01b031661013160008484815181106133f4576133f46159f5565b6020908102919091018101516001600160e01b0319168252810191909152604001600020546001600160a01b03160361348f5760006101316000848481518110613440576134406159f5565b60200260200101516001600160e01b0319166001600160e01b031916815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b6001016133ca565b60005b82518110156134fd576134f4848360008685815181106134bc576134bc6159f5565b60200260200101516001600160e01b0319166001600160e01b031916815260200190815260200160002061427890919063ffffffff16565b5060010161349a565b50505050565b60006112227f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61353260c95490565b60ca546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b60606132bd848484604051806060016040528060298152602001615d696029913961428d565b604051637921219560e11b81526001600160a01b0382169063f242432a906135da90309088908b908b908a908a90600401615a0b565b600060405180830381600087803b1580156135f457600080fd5b505af1158015613608573d6000803e3d6000fd5b50505050505050505050565b61361c614368565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600054610100900460ff1661368d5760405162461bcd60e51b815260040161191a90615a46565b6136e586868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260018152603160f81b602082015291506143b19050565b6136ee886143e2565b6136fd87878787878787614422565b5050505050505050565b6001600160a01b038416600090815261012e602052604090205460ff166137415760405163a826b79f60e01b815260040160405180910390fd5b60008490506137b585826001600160a01b031663fa771d6f6040518163ffffffff1660e01b8152600401600060405180830381865afa158015613788573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526137b09190810190615a91565b6132f7565b61382485826001600160a01b031663072b88f06040518163ffffffff1660e01b8152600401600060405180830381865afa1580156137f7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261381f9190810190615a91565b6133c7565b61389685826001600160a01b031663abd9e8b26040518163ffffffff1660e01b8152600401600060405180830381865afa158015613866573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261388e9190810190615a91565b61012f613497565b61390885826001600160a01b031663fa7d91db6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156138d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139009190810190615a91565b610130613497565b6001600160a01b038516600090815261012e60205260409020805460ff19169055811561399457604051638a91b0e360e01b81526001600160a01b03821690638a91b0e39061395d9087908790600401615b2a565b600060405180830381600087803b15801561397757600080fd5b505af115801561398b573d6000803e3d6000fd5b50505050613ab6565b604051638a91b0e360e01b81526001600160a01b03821690638a91b0e3906139c29087908790600401615b2a565b600060405180830381600087803b1580156139dc57600080fd5b505af19250505080156139ed575060015b613ab6576139f9615b3e565b806308c379a003613a555750613a0d615b5a565b80613a185750613a57565b7f025a8d44fca5147c423a6a02438cb8d6356a48a281c257c915fbc4d73746228881604051613a479190614de4565b60405180910390a150613ab6565b505b3d808015613a81576040519150601f19603f3d011682016040523d82523d6000602084013e613a86565b606091505b507f025a8d44fca5147c423a6a02438cb8d6356a48a281c257c915fbc4d73746228881604051613a479190614de4565b6040516001600160a01b038616907f193a1765d1ac3f738ffc2a4803be4496d1e89ac2b4994cba4643b8d8a36eede890600090a25050505050565b6001600160a01b038316600090815261012e602052604090205460ff1615613b2c57604051636972275b60e11b815260040160405180910390fd5b6040516301ffc9a760e01b815283906001600160a01b038216906301ffc9a790613b61906350a5e2e560e01b906004016157b2565b602060405180830381865afa158015613b7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ba29190615795565b613bd557604051635fd8edab60e11b8152702737ba1024a9b4b6b83632a8363ab3b4b760791b600482015260240161191a565b613bde816144a0565b613be7816145e0565b613c5984826001600160a01b031663abd9e8b26040518163ffffffff1660e01b8152600401600060405180830381865afa158015613c29573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c519190810190615a91565b61012f614720565b613ccb84826001600160a01b031663fa7d91db6040518163ffffffff1660e01b8152600401600060405180830381865afa158015613c9b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613cc39190810190615a91565b610130614720565b6001600160a01b03808516600090815261012e602052604090819020805460ff19166001179055516306d61fe760e41b815290821690636d61fe7090613d179086908690600401615b2a565b600060405180830381600087803b158015613d3157600080fd5b505af1158015613d45573d6000803e3d6000fd5b50506040516001600160a01b03871692507f1dc3a7c7f672709e4661a9ca6b2acd21a696b4560ed2e2e4056e3b45d0f971599150600090a250505050565b6040516001600160a01b038216904780156108fc02916000818181858888f19350505050158015611533573d6000803e3d6000fd5b60405163a9059cbb60e01b81526001600160a01b0383811660048301526024820185905282169063a9059cbb906044016020604051808303816000875af1158015613e07573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fd9190615795565b613e33614786565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586136493390565b600054610100900460ff16613e8f5760405162461bcd60e51b815260040161191a90615a46565b610101805460ff60a81b1916600160a81b8315158102919091179182905560ff91041615611a3457506101015461010280546101009092046001600160a01b03166001600160a01b0319909216919091179055565b61010154604051636361ddf360e11b815260009161010090046001600160a01b03169063c6c3bbe690613f1f90879087908790600401615848565b600060405180830381600087803b158015613f3957600080fd5b505af1158015613f4d573d6000803e3d6000fd5b50505050613f5b83836147cc565b5060019392505050565b61010154604051633dae446f60e21b815260009161010090046001600160a01b03169063f6b911bc90613fa090879087908790600401615848565b600060405180830381600087803b158015613fba57600080fd5b505af1158015613fce573d6000803e3d6000fd5b50505050613f5b83836147d8565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161402191815260200190565b60405180910390a3505050565b33600090815261012e602052604090205460609060ff166140625760405163028b1dd160e41b815260040160405180910390fd5b611e5a83838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525030939250506147e49050565b6000198214611533576033546040516377b59c2f60e11b8152600481018490526001600160a01b0383811660248301529091169063ef6b385e9060440160006040518083038186803b1580156140f957600080fd5b505afa158015611341573d6000803e3d6000fd5b604051632142170760e11b81526001600160a01b038216906342842e0e9061413d90309086908890600401615848565b600060405180830381600087803b15801561415757600080fd5b505af1158015612a53573d6000803e3d6000fd5b6001600160a01b038116600090815260fe60205260409020805490614191816001614828565b50919050565b6000610f8f6141a4613503565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000806141d688888888614845565b9250925092506141e68282614914565b50909695505050505050565b6000826000018281548110614209576142096159f5565b9060005260206000200154905092915050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561426c57602002820191906000526020600020905b815481526020019060010190808311614258575b50505050509050919050565b6000611e5a836001600160a01b0384166149cd565b6060824710156142ee5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161191a565b600080866001600160a01b0316858760405161430a9190615be3565b60006040518083038185875af1925050503d8060008114614347576040519150601f19603f3d011682016040523d82523d6000602084013e61434c565b606091505b509150915061435d87838387614ac0565b979650505050505050565b60655460ff1661183c5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161191a565b600054610100900460ff166143d85760405162461bcd60e51b815260040161191a90615a46565b6115338282614b39565b600054610100900460ff166144095760405162461bcd60e51b815260040161191a90615a46565b61441281614b7a565b61441a614baa565b611a34614bd9565b600054610100900460ff166144495760405162461bcd60e51b815260040161191a90615a46565b6101018054610100600160a81b0319166101006001600160a01b038a160217905560ff614477868883615c47565b50610100614486848683615c47565b50610101805460ff191660ff8416179055612a5381613e68565b6000816001600160a01b031663fa771d6f6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156144e0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526145089190810190615a91565b905060005b81518110156119a957600082828151811061452a5761452a6159f5565b6020908102919091018101516001600160e01b0319811660009081526101329092526040909120549091506001600160a01b0316156145a6576001600160e01b0319811660009081526101326020526040908190205490516332078b8f60e01b815261191a9183916001600160a01b0390911690600401615d06565b6001600160e01b03191660009081526101326020526040902080546001600160a01b0319166001600160a01b03851617905560010161450d565b6000816001600160a01b031663072b88f06040518163ffffffff1660e01b8152600401600060405180830381865afa158015614620573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526146489190810190615a91565b905060005b81518110156119a957600082828151811061466a5761466a6159f5565b6020908102919091018101516001600160e01b0319811660009081526101319092526040909120549091506001600160a01b0316156146e6576001600160e01b0319811660009081526101316020526040908190205490516332078b8f60e01b815261191a9183916001600160a01b0390911690600401615d06565b6001600160e01b03191660009081526101316020526040902080546001600160a01b0319166001600160a01b03851617905560010161464d565b60005b82518110156134fd5761477d84836000868581518110614745576147456159f5565b60200260200101516001600160e01b0319166001600160e01b0319168152602001908152602001600020614c0090919063ffffffff16565b50600101614723565b60655460ff161561183c5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161191a565b61153360008383613fdc565b61153382600083613fdc565b6060611e5a838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061428d565b8082600001600082825461483c9190615d29565b90915550505050565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115614880575060009150600390508261490a565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156148d4573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166149005750600092506001915082905061490a565b9250600091508190505b9450945094915050565b600082600381111561492857614928615d3c565b03614931575050565b600182600381111561494557614945615d3c565b036149635760405163f645eedf60e01b815260040160405180910390fd5b600282600381111561497757614977615d3c565b036149985760405163fce698f760e01b81526004810182905260240161191a565b60038260038111156149ac576149ac615d3c565b03611533576040516335e2f38360e21b81526004810182905260240161191a565b60008181526001830160205260408120548015614ab65760006149f16001836156d9565b8554909150600090614a05906001906156d9565b9050808214614a6a576000866000018281548110614a2557614a256159f5565b9060005260206000200154905080876000018481548110614a4857614a486159f5565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080614a7b57614a7b615d52565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610f8f565b6000915050610f8f565b60608315614b2f578251600003614b28576001600160a01b0385163b614b285760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161191a565b50816132bd565b6132bd8383614c15565b600054610100900460ff16614b605760405162461bcd60e51b815260040161191a90615a46565b81516020928301208151919092012060c99190915560ca55565b600054610100900460ff16614ba15760405162461bcd60e51b815260040161191a90615a46565b611a3481614c3f565b600054610100900460ff16614bd15760405162461bcd60e51b815260040161191a90615a46565b61183c614cdf565b600054610100900460ff1661183c5760405162461bcd60e51b815260040161191a90615a46565b6000611e5a836001600160a01b038416614d12565b815115614c255781518083602001fd5b8060405162461bcd60e51b815260040161191a9190614de4565b600054610100900460ff16614c665760405162461bcd60e51b815260040161191a90615a46565b603380546001600160a01b0319166001600160a01b038316908117909155634420e486336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015614ccb57600080fd5b505af115801561163c573d6000803e3d6000fd5b600054610100900460ff16614d065760405162461bcd60e51b815260040161191a90615a46565b6065805460ff19169055565b6000818152600183016020526040812054614d5957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610f8f565b506000610f8f565b6001600160e01b031981168114611a3457600080fd5b600060208284031215614d8957600080fd5b8135611e5a81614d61565b60005b83811015614daf578181015183820152602001614d97565b50506000910152565b60008151808452614dd0816020860160208601614d94565b601f01601f19169290920160200192915050565b602081526000611e5a6020830184614db8565b6001600160a01b0381168114611a3457600080fd5b60008060408385031215614e1f57600080fd5b8235614e2a81614df7565b946020939093013593505050565b60008151808452602080850194506020840160005b83811015614e725781516001600160a01b031687529582019590820190600101614e4d565b509495945050505050565b602080825282516001600160e01b0319168282015282015160806040830152600090614eac60a0840182614e38565b60408501516001600160a01b0316606085810191909152850151848203601f19016080860152909150614edf8282614e38565b95945050505050565b60008060408385031215614efb57600080fd5b50508035926020909101359150565b600080600060608486031215614f1f57600080fd5b8335614f2a81614df7565b92506020840135614f3a81614df7565b929592945050506040919091013590565b600060208284031215614f5d57600080fd5b5035919050565b60008060408385031215614f7757600080fd5b823591506020830135614f8981614df7565b809150509250929050565b60008083601f840112614fa657600080fd5b5081356001600160401b03811115614fbd57600080fd5b6020830191508360208260051b8501011115614fd857600080fd5b9250929050565b600080600080600060608688031215614ff757600080fd5b853561500281614df7565b945060208601356001600160401b038082111561501e57600080fd5b61502a89838a01614f94565b9096509450604088013591508082111561504357600080fd5b5061505088828901614f94565b969995985093965092949392505050565b60008083601f84011261507357600080fd5b5081356001600160401b0381111561508a57600080fd5b602083019150836020828501011115614fd857600080fd5b600080600080606085870312156150b857600080fd5b84356150c381614df7565b93506020850135925060408501356001600160401b038111156150e557600080fd5b6150f187828801615061565b95989497509550505050565b60008060008060008060a0878903121561511657600080fd5b8635955060208701359450604087013561512f81614df7565b935060608701356001600160401b0381111561514a57600080fd5b61515689828a01615061565b909450925050608087013561516a81614df7565b809150509295509295509295565b803560ff8116811461518957600080fd5b919050565b8015158114611a3457600080fd5b60008060008060008060008060c0898b0312156151b857600080fd5b88356151c381614df7565b975060208901356151d381614df7565b965060408901356001600160401b03808211156151ef57600080fd5b6151fb8c838d01615061565b909850965060608b013591508082111561521457600080fd5b506152218b828c01615061565b9095509350615234905060808a01615178565b915060a08901356152448161518e565b809150509295985092959890939650565b60008060006040848603121561526a57600080fd5b833561527581614df7565b925060208401356001600160401b0381111561529057600080fd5b61529c86828701615061565b9497909650939450505050565b6000602082840312156152bb57600080fd5b8135611e5a81614df7565b602081526000611e5a6020830184614e38565b6000806000606084860312156152ee57600080fd5b83359250602084013561530081614df7565b9150604084013561531081614df7565b809150509250925092565b60006020828403121561532d57600080fd5b8135611e5a8161518e565b6000806020838503121561534b57600080fd5b82356001600160401b0381111561536157600080fd5b61536d85828601615061565b90969095509350505050565b600060c0828403121561419157600080fd5b600080600080600080600060a0888a0312156153a657600080fd5b87356153b181614df7565b965060208801356001600160401b03808211156153cd57600080fd5b6153d98b838c01615061565b909850965060408a013591506153ee82614df7565b9094506060890135908082111561540457600080fd5b506154118a828b01615061565b90945092505060808801356154258161518e565b8091505092959891949750929550565b600080600080600080600060e0888a03121561545057600080fd5b873561545b81614df7565b9650602088013561546b81614df7565b9550604088013594506060880135935061548760808901615178565b925060a0880135915060c0880135905092959891949750929550565b600080604083850312156154b657600080fd5b82356154c181614df7565b91506020830135614f8981614df7565b6020815260008251608060208401526154ed60a0840182614db8565b905060018060a01b03602085015116604084015263ffffffff60e01b6040850151166060840152606084015160808401528091505092915050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b038111828210171561556357615563615528565b6040525050565b60006020828403121561557c57600080fd5b81516001600160401b038082111561559357600080fd5b818401915084601f8301126155a757600080fd5b8151818111156155b9576155b9615528565b60405191506155d2601f8201601f19166020018361553e565b8082528560208285010111156155e757600080fd5b6155f8816020840160208601614d94565b50949350505050565b600181811c9082168061561557607f821691505b60208210810361419157634e487b7160e01b600052602260045260246000fd5b60006020828403121561564757600080fd5b5051919050565b60006020828403121561566057600080fd5b8151611e5a81614df7565b6000808585111561567b57600080fd5b8386111561568857600080fd5b5050820193919092039150565b6001600160e01b031981358181169160048510156111a05760049490940360031b84901b1690921692915050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610f8f57610f8f6156c3565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038516815283602082015260606040820152600061573d6060830184866156ec565b9695505050505050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6000602082840312156157a757600080fd5b8151611e5a8161518e565b6001600160e01b031991909116815260200190565b600080600080608085870312156157dd57600080fd5b84356157e881614df7565b935060208501356157f881614df7565b9250604085013561580881614df7565b9396929550929360600135925050565b60008060006060848603121561582d57600080fd5b833561583881614df7565b9250602084013561530081614df7565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600080600080600060a0868803121561588457600080fd5b853561588f81614df7565b9450602086013561589f81614df7565b935060408601356158af81614df7565b94979396509394606081013594506080013592915050565b6000826158e457634e487b7160e01b600052601260045260246000fd5b500690565b60006001600160401b0382111561590257615902615528565b5060051b60200190565b60008060006060848603121561592157600080fd5b833561592c81614df7565b9250602084810135925060408501356001600160401b0381111561594f57600080fd5b8501601f8101871361596057600080fd5b803561596b816158e9565b604051615978828261553e565b82815260059290921b830184019184810191508983111561599857600080fd5b928401925b828410156159bf5783356159b081614df7565b8252928401929084019061599d565b80955050505050509250925092565b60018060a01b0384168152826020820152606060408201526000614edf6060830184614e38565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03878116825286166020820152604081018590526060810184905260a06080820181905260009061174890830184866156ec565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60006020808385031215615aa457600080fd5b82516001600160401b03811115615aba57600080fd5b8301601f81018513615acb57600080fd5b8051615ad6816158e9565b604051615ae3828261553e565b82815260059290921b8301840191848101915087831115615b0357600080fd5b928401925b8284101561435d578351615b1b81614d61565b82529284019290840190615b08565b6020815260006132bd6020830184866156ec565b600060033d1115615b575760046000803e5060005160e01c5b90565b600060443d1015615b685790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715615b9757505050505090565b8285019150815181811115615baf5750505050505090565b843d8701016020828501011115615bc95750505050505090565b615bd86020828601018761553e565b509095945050505050565b60008251615bf5818460208701614d94565b9190910192915050565b601f8211156119a9576000816000526020600020601f850160051c81016020861015615c285750805b601f850160051c820191505b8181101561134157828155600101615c34565b6001600160401b03831115615c5e57615c5e615528565b615c7283615c6c8354615601565b83615bff565b6000601f841160018114615ca65760008515615c8e5750838201355b600019600387901b1c1916600186901b17835561163c565b600083815260209020601f19861690835b82811015615cd75786850135825560209485019460019092019101615cb7565b5086821015615cf45760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6001600160e01b03199290921682526001600160a01b0316602082015260400190565b80820180821115610f8f57610f8f6156c3565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fdfe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a264697066735822122066590ac71bd682829c704720de8970bced0bc5eac2c9e9532da134102c27d5b364736f6c63430008180033
Deployed Bytecode
0x6080604052600436106104095760003560e01c80638387aa0411610213578063a8aa987a11610123578063d91eff61116100ab578063ef18374a1161007a578063ef18374a14610c9c578063f1e152df14610cb1578063f2fde38b14610cd1578063fbfa77cf14610cf1578063fe523e1914610d1257610410565b8063d91eff6114610c29578063dd62ed3e14610c49578063df592f7d14610c69578063ec27e0b714610c8957610410565b8063c6288f35116100f2578063c6288f3514610b94578063ca15c87314610bb4578063d505accf14610bd4578063d547741f14610bf4578063d5abeb0114610c1457610410565b8063a8aa987a14610b14578063a9059cbb14610b34578063b37f3a2414610b54578063bee547e114610b7457610410565b80639358928b116101a6578063a217fddf11610175578063a217fddf14610a8c578063a24a517d14610aa1578063a50fdd5514610ac1578063a58b409b14610ae1578063a7a2bba414610af457610410565b80639358928b14610a2f57806394ed11e714610a4457806395d89b4114610a5757806397f735d514610a6c57610410565b80638da5cb5b116101e25780638da5cb5b146109ba5780639010d07c146109cf57806391d14854146109ef57806392e3a3e214610a0f57610410565b80638387aa04146109455780638456cb591461096557806384955c881461097a5780638bb9c5bf1461099a57610410565b806336568abe1161031957806351cff8d9116102a15780635d29dab4116102705780635d29dab4146108ae578063604269d1146108ce57806370a08231146108f05780637ecc2b56146109105780637ecebe001461092557610410565b806351cff8d91461082957806357b22d2d1461084957806359355736146108765780635c975abb1461089657610410565b80634000aea0116102e85780634000aea01461076857806340910fd91461078857806343a68ae5146107a857806344aba123146107c85780634842ce511461080957610410565b806336568abe1461070057806338997b11146107205780633c6182ef146107335780633f4ba83a1461075357610410565b806323b872dd1161039c578063313ce5671161036b578063313ce5671461066e57806332e7a3cb1461069b5780633408e470146106b857806336034372146106cb5780633644e515146106eb57610410565b806323b872dd146105ee578063248a9ca31461060e57806326bdf1211461062e5780632f2ff15d1461064e57610410565b80631584ba38116103d85780631584ba381461054557806318160ddd1461057c5780631d1891df1461059f5780631e4e0091146105cc57610410565b806301ffc9a714610490578063024fd650146104c557806306fdde0314610503578063095ea7b31461052557610410565b3661041057005b6000366060600061041f610d43565b6040808201516001600160e01b031916600090815261013160205220549091506001600160a01b031661046557604051631661b6e560e11b815260040160405180910390fd5b61046e81610dcd565b5061047881610efc565b915061048381610f95565b5050915050805190602001f35b34801561049c57600080fd5b506104b06104ab366004614d77565b6110ab565b60405190151581526020015b60405180910390f35b3480156104d157600080fd5b50610101546104eb9061010090046001600160a01b031681565b6040516001600160a01b0390911681526020016104bc565b34801561050f57600080fd5b506105186110e5565b6040516104bc9190614de4565b34801561053157600080fd5b506104b0610540366004614e0c565b611173565b34801561055157600080fd5b506104eb610560366004614d77565b610132602052600090815260409020546001600160a01b031681565b34801561058857600080fd5b506105916111a8565b6040519081526020016104bc565b3480156105ab57600080fd5b506105bf6105ba366004614d77565b611227565b6040516104bc9190614e7d565b3480156105d857600080fd5b506105ec6105e7366004614ee8565b6112cc565b005b3480156105fa57600080fd5b506104b0610609366004614f0a565b611349565b34801561061a57600080fd5b50610591610629366004614f4b565b611380565b34801561063a57600080fd5b506104eb610649366004614f4b565b6113ef565b34801561065a57600080fd5b506105ec610669366004614f64565b611463565b34801561067a57600080fd5b50610101546106899060ff1681565b60405160ff90911681526020016104bc565b3480156106a757600080fd5b506105916518985b9b995960d21b81565b3480156106c457600080fd5b5046610591565b3480156106d757600080fd5b506105ec6106e6366004614fdf565b611537565b3480156106f757600080fd5b50610591611643565b34801561070c57600080fd5b506105ec61071b366004614f64565b61164d565b61051861072e3660046150a2565b611656565b34801561073f57600080fd5b506105ec61074e3660046150fd565b611754565b34801561075f57600080fd5b506105ec6117cb565b34801561077457600080fd5b506104b06107833660046150a2565b61183e565b34801561079457600080fd5b506105ec6107a336600461519c565b6118dc565b3480156107b457600080fd5b506105ec6107c3366004615255565b611993565b3480156107d457600080fd5b506104eb6107e3366004614d77565b6001600160e01b031916600090815261013160205260409020546001600160a01b031690565b34801561081557600080fd5b506105ec610824366004615255565b6119ae565b34801561083557600080fd5b506105ec6108443660046152a9565b6119c2565b34801561085557600080fd5b50610869610864366004614d77565b611a37565b6040516104bc91906152c6565b34801561088257600080fd5b506105916108913660046152a9565b611a5d565b3480156108a257600080fd5b5060655460ff166104b0565b3480156108ba57600080fd5b506105ec6108c93660046152d9565b611a96565b3480156108da57600080fd5b50610101546104b090600160a81b900460ff1681565b3480156108fc57600080fd5b5061059161090b3660046152a9565b611b0a565b34801561091c57600080fd5b50610591611b43565b34801561093157600080fd5b506105916109403660046152a9565b611b99565b34801561095157600080fd5b506105ec6109603660046152a9565b611bb7565b34801561097157600080fd5b506105ec611c11565b34801561098657600080fd5b506105916109953660046152a9565b611c82565b3480156109a657600080fd5b506105ec6109b5366004614f4b565b611cbb565b3480156109c657600080fd5b506104eb611d77565b3480156109db57600080fd5b506104eb6109ea366004614ee8565b611de5565b3480156109fb57600080fd5b506104b0610a0a366004614f64565b611e61565b348015610a1b57600080fd5b506105ec610a2a36600461531b565b611ed7565b348015610a3b57600080fd5b50610591611f77565b610518610a52366004615338565b611fbd565b348015610a6357600080fd5b50610518612780565b348015610a7857600080fd5b506104b0610a873660046152a9565b61278e565b348015610a9857600080fd5b50610591600081565b348015610aad57600080fd5b506105ec610abc3660046152a9565b6127fe565b348015610acd57600080fd5b506033546104eb906001600160a01b031681565b6105ec610aef366004615379565b612830565b348015610b0057600080fd5b506105ec610b0f366004614f64565b612972565b348015610b2057600080fd5b506105ec610b2f3660046152d9565b61299c565b348015610b4057600080fd5b506104b0610b4f366004614e0c565b612a10565b348015610b6057600080fd5b506105ec610b6f36600461538b565b612a33565b348015610b8057600080fd5b506105ec610b8f366004615255565b612a5c565b348015610ba057600080fd5b50610869610baf366004614d77565b612a72565b348015610bc057600080fd5b50610591610bcf366004614f4b565b612a98565b348015610be057600080fd5b506105ec610bef366004615435565b612aca565b348015610c0057600080fd5b506105ec610c0f366004614f64565b612c50565b348015610c2057600080fd5b50610591612d24565b348015610c3557600080fd5b506105916836b7b232b930ba37b960b91b81565b348015610c5557600080fd5b50610591610c643660046154a3565b612d7a565b348015610c7557600080fd5b506104b0610c843660046152a9565b612df7565b6105ec610c97366004615379565b612e2a565b348015610ca857600080fd5b50610591612f4e565b348015610cbd57600080fd5b50610591610ccc3660046152a9565b612fa4565b348015610cdd57600080fd5b506105ec610cec3660046152a9565b612fdd565b348015610cfd57600080fd5b50610102546104eb906001600160a01b031681565b348015610d1e57600080fd5b506104b0610d2d3660046152a9565b61012e6020526000908152604090205460ff1681565b60408051608081018252606080825260006020830181905292820183905281019190915260405180608001604052806000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250938552505033602084015250356001600160e01b031916604082015234606090910152919050565b6040808201516001600160e01b031916600090815261012f60205220606090610df590613099565b600003610e1f576040805160016020820152015b6040516020818303038152906040529050919050565b6040808301516001600160e01b031916600090815261012f602052908120610e4690613099565b905060005b81811015610ef5576040808501516001600160e01b031916600090815261012f60205220610e7990826130a3565b6001600160a01b031663d980b8d9856040518263ffffffff1660e01b8152600401610ea491906154d1565b6000604051808303816000875af1158015610ec3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610eeb919081019061556a565b9250600101610e4b565b5050919050565b6040808201516001600160e01b0319166000908152610131602052819020549051639099c17560e01b81526060916001600160a01b031690639099c17590610f489085906004016154d1565b6000604051808303816000875af1158015610f67573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f8f919081019061556a565b92915050565b6040808201516001600160e01b031916600090815261013060205220606090610fbd90613099565b600003610fd557604080516001602082015201610e09565b6040808301516001600160e01b0319166000908152610130602052908120610ffc90613099565b905060005b81811015610ef5576040808501516001600160e01b03191660009081526101306020522061102f90826130a3565b6001600160a01b03166352b4392c856040518263ffffffff1660e01b815260040161105a91906154d1565b6000604051808303816000875af1158015611079573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110a1919081019061556a565b9250600101611001565b60006110b6826130af565b806110c557506110c5826130ff565b80610f8f57506001600160e01b03198216634ddc0f0f60e11b1492915050565b60ff80546110f290615601565b80601f016020809104026020016040519081016040528092919081815260200182805461111e90615601565b801561116b5780601f106111405761010080835404028352916020019161116b565b820191906000526020600020905b81548152906001019060200180831161114e57829003601f168201915b505050505081565b60008061117e610d43565b905061118981610dcd565b50611195338585613160565b91506111a081610f95565b505092915050565b600061010160019054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112229190615635565b905090565b6040805160808101825260008082526060602083018190529282015281810191909152604080516080810182526001600160e01b03198416808252600090815261012f6020908152929020909182019061128090613224565b81526001600160e01b03198416600081815261013160209081526040808320546001600160a01b03168286015292825261013090528190209101906112c490613224565b905292915050565b6033546001600160a01b0316630997ce71336040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526024810185905260448101849052606401600060405180830381600087803b15801561132d57600080fd5b505af1158015611341573d6000803e3d6000fd5b505050505050565b600080611354610d43565b905061135f81610dcd565b5061136c33868686613231565b915061137781610f95565b50509392505050565b603354604051632b25c9c760e01b8152600481018390526000916001600160a01b031690632b25c9c7906024015b602060405180830381865afa1580156113cb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8f9190615635565b61010154604051638ea6902960e01b81526004810183905260009161010090046001600160a01b031690638ea6902990602401602060405180830381865afa15801561143f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8f919061564e565b61146d8282611e61565b611533576033546001600160a01b0316633290f93a336040516001600160e01b031960e084901b1681526001600160a01b039182166004820152602481018690529084166044820152606401600060405180830381600087803b1580156114d357600080fd5b505af11580156114e7573d6000803e3d6000fd5b505050506114f23390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b611540336132c5565b61157d858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132f792505050565b6115ba858383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506133c792505050565b6115fb8583838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061012f9250613497915050565b61163c858383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506101309250613497915050565b5050505050565b6000611222613503565b61153382611cbb565b33600090815261012e602052604090205460609060ff1661168a5760405163028b1dd160e41b815260040160405180910390fd5b6001600160a01b038516600090815261012e6020526040902054859060ff16156116c75760405163040846c960e11b815260040160405180910390fd5b60006116d6600482868861566b565b6116df91615695565b905060008634116116f15760006116fb565b6116fb87346156d9565b905061174886868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050506001600160a01b038b169190508961357e565b98975050505050505050565b6033546001600160a01b031663765e9fa6336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160006040518083038186803b1580156117a557600080fd5b505afa1580156117b9573d6000803e3d6000fd5b505050506113418686868686866135a4565b6033546001600160a01b031663765e9fa6336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160006040518083038186803b15801561181c57600080fd5b505afa158015611830573d6000803e3d6000fd5b5050505061183c613614565b565b600080611849610d43565b905061185481610dcd565b5061186133338888613231565b9150856001600160a01b03811663a4c0ed36338888886040518563ffffffff1660e01b81526004016118969493929190615715565b600060405180830381600087803b1580156118b057600080fd5b505af11580156118c4573d6000803e3d6000fd5b50505050506118d281610f95565b5050949350505050565b600054600290610100900460ff161580156118fe575060005460ff8083169116105b6119235760405162461bcd60e51b815260040161191a90615747565b60405180910390fd5b6000805461ffff191660ff8316176101001790556119478989898989898989613666565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050505050505050565b61199c336132c5565b6119a98383836001613707565b505050565b6119b7336132c5565b6119a9838383613af1565b6033546001600160a01b031663765e9fa6336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160006040518083038186803b158015611a1357600080fd5b505afa158015611a27573d6000803e3d6000fd5b50505050611a3481613d83565b50565b6001600160e01b03198116600090815261012f60205260409020606090610f8f90613224565b61010154604051632c9aab9b60e11b81526001600160a01b038381166004830152600092610100900416906359355736906024016113ae565b6033546001600160a01b031663765e9fa6336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160006040518083038186803b158015611ae757600080fd5b505afa158015611afb573d6000803e3d6000fd5b505050506119a9838383613db8565b610101546040516370a0823160e01b81526001600160a01b038381166004830152600092610100900416906370a08231906024016113ae565b600061010160019054906101000a90046001600160a01b03166001600160a01b0316637ecc2b566040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111fe573d6000803e3d6000fd5b6001600160a01b038116600090815260fe6020526040812054610f8f565b6033546040516320e1ea8160e21b81526001600160a01b03838116600483015290911690638387aa04906024015b60006040518083038186803b158015611bfd57600080fd5b505afa15801561163c573d6000803e3d6000fd5b6033546001600160a01b031663765e9fa6336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160006040518083038186803b158015611c6257600080fd5b505afa158015611c76573d6000803e3d6000fd5b5050505061183c613e2b565b61010154604051631092ab9160e31b81526001600160a01b038381166004830152600092610100900416906384955c88906024016113ae565b6033546001600160a01b031663f3c3437d336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b158015611d1557600080fd5b505af1158015611d29573d6000803e3d6000fd5b50505050611d343390565b6001600160a01b0316336001600160a01b0316827ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a450565b6033546040805163208f1f9960e01b815290516000926001600160a01b03169163208f1f999160048083019260209291908290030181865afa158015611dc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611222919061564e565b6033546040516338c43adf60e11b815260048101849052602481018390526000916001600160a01b03169063718875be90604401602060405180830381865afa158015611e36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e5a919061564e565b9392505050565b603354604051635219898160e11b8152600481018490526001600160a01b038381166024830152600092169063a433130290604401602060405180830381865afa158015611eb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e5a9190615795565b600054600290610100900460ff16158015611ef9575060005460ff8083169116105b611f155760405162461bcd60e51b815260040161191a90615747565b6000805461ffff191660ff831617610100179055611f3282613e68565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b61010154600090600160a81b900460ff1615611fb55761010254611fa3906001600160a01b0316611b0a565b611fab6111a8565b61122291906156d9565b6112226111a8565b33600090815261012e602052604090205460609060ff16611ff15760405163028b1dd160e41b815260040160405180910390fd5b6004821115612776576000612009600482858761566b565b61201291615695565b905063039cbf0d60e21b6001600160e01b03198216016120cf576084831461204f57806040516313efbce360e31b815260040161191a91906157b2565b6000808080612061876004818b61566b565b81019061206e91906157c7565b935093509350935061208284848484613231565b6120a6576040805160006020820152016040516020818303038152906040526120c3565b6040805160016020820152015b6040516020818303038152906040525b95505050505050610f8f565b631c9e220d60e11b6001600160e01b0319821601612185576064831461210a57806040516313efbce360e31b815260040161191a91906157b2565b6000808061211b866004818a61566b565b8101906121289190614f0a565b925092509250612139838383613ee4565b61215d5760408051600060208201520160405160208183030381529060405261217a565b6040805160016020820152015b6040516020818303038152906040525b945050505050610f8f565b630251bb9160e21b6001600160e01b03198216016121ef57606483146121c057806040516313efbce360e31b815260040161191a91906157b2565b600080806121d1866004818a61566b565b8101906121de9190614f0a565b925092509250612139838383613f65565b6339e6e22f60e21b6001600160e01b0319821601612259576064831461222a57806040516313efbce360e31b815260040161191a91906157b2565b6000808061223b866004818a61566b565b8101906122489190614f0a565b925092509250612139838383613160565b63540861fb60e11b6001600160e01b031982160161239c576064831461229457806040516313efbce360e31b815260040161191a91906157b2565b600080806122a5866004818a61566b565b8101906122b29190615818565b61010154604051632bf79e0560e11b81526001600160a01b0380861660048301528085166024830152808416604483015294975092955090935060009261010090910416906357ef3c0a906064016020604051808303816000875af115801561231f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123439190615635565b90507fb6153b6bd7894806f48017bc32f1de542ca0b4b97bf5dd9a43ec5c52fabd21a883838360405161237893929190615848565b60405180910390a161238b838383613fdc565b6040805160208101839052016120b3565b6338cec1f160e21b6001600160e01b03198216016124bb5760a483146123d757806040516313efbce360e31b815260040161191a91906157b2565b6000808080806123ea886004818c61566b565b8101906123f7919061586c565b610101546040516307313e0f60e21b81526001600160a01b038088166004830152808716602483015280861660448301526064820185905260848201849052969b509499509297509095509350610100900490911690631cc4f83c9060a401600060405180830381600087803b15801561247057600080fd5b505af1158015612484573d6000803e3d6000fd5b50505050612493848484613fdc565b6040805160016020820152016040516020818303038152906040529650505050505050610f8f565b63f3f9e74b60e01b6001600160e01b031982160161259a57606483146124f657806040516313efbce360e31b815260040161191a91906157b2565b60008080612507866004818a61566b565b8101906125149190614f0a565b61010154604051630c0618b560e01b8152939650919450925061010090046001600160a01b031690630c0618b59061255490869086908690600401615848565b600060405180830381600087803b15801561256e57600080fd5b505af1158015612582573d6000803e3d6000fd5b50505050600160405160200161216a91815260200190565b63064e9c1560e41b6001600160e01b03198216016126555760a4831080156125d7575060206125ca6004856156d9565b6125d491906158c7565b15155b156125f757806040516313efbce360e31b815260040161191a91906157b2565b60008080612608866004818a61566b565b810190612615919061590c565b610101546040516309b163eb60e41b8152939650919450925061010090046001600160a01b031690639b163eb090612554908690869086906004016159ce565b63a2e5b8b160e01b6001600160e01b0319821601612774576064831461269057806040516313efbce360e31b815260040161191a91906157b2565b600080806126a1866004818a61566b565b8101906126ae9190615818565b61010154604051635d1a474f60e01b81526001600160a01b038086166004830152808516602483015280841660448301529497509295509093506000926101009091041690635d1a474f906064016020604051808303816000875af115801561271b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273f9190615635565b90507f2283dd8f0aa4512bb878b51898d84e80c33b3620cba1edaad7f13e555e097c9c83838360405161237893929190615848565b505b611e5a838361402e565b61010080546110f290615601565b60335460405163b924698760e01b81526001600160a01b038381166004830152600092169063b9246987906024015b602060405180830381865afa1580156127da573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8f9190615795565b6033546040516389c75e1160e01b81526001600160a01b038381166004830152909116906389c75e1190602401611be5565b600061283a610d43565b905061284581610dcd565b507f3fd4a614bd02c8fb908a3b3a05852476cf4c63cfc1b7280860fd956aa0982f9f61287181336140a4565b61010154600160a81b900460ff16156128b657610102546128b0906001600160a01b0316806128a660608701604088016152a9565b8660a00135613231565b506128d6565b6128d4336128ca60608601604087016152a9565b8560a00135613ee4565b505b60016128e860608501604086016152a9565b6001600160a01b031661290160408601602087016152a9565b6001600160a01b03167ff4ea29784a8ad7456fb8ea0b9af463d31bde69edb825d92a73ca63096227b76d60a087013561293d60208901896152a9565b604080519283526001600160a01b03919091166020830152606089810135838301529051918290030190a4506119a981610f95565b61297a611d77565b6001600160a01b0316816001600160a01b0316146115335761153382826140a4565b6033546001600160a01b031663765e9fa6336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160006040518083038186803b1580156129ed57600080fd5b505afa158015612a01573d6000803e3d6000fd5b505050506119a983838361410d565b600080612a1b610d43565b9050612a2681610dcd565b5061119533338686613231565b612a3c336132c5565b612a4887878784613707565b612a53848484613af1565b50505050505050565b612a65336132c5565b6119a98383836000613707565b6001600160e01b03198116600090815261013060205260409020606090610f8f90613224565b60335460405163bdb44f2960e01b8152600481018390526000916001600160a01b03169063bdb44f29906024016113ae565b6000612ad4610d43565b9050612adf81610dcd565b5084421115612b305760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e65000000604482015260640161191a565b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9898989612b5f8d61416b565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e0016040516020818303038152906040528051906020012090506000612bba82614197565b90506000612bca828888886141c4565b90508a6001600160a01b0316816001600160a01b031614612c2d5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e61747572650000604482015260640161191a565b612c388b8b8b613160565b50505050612c4581610f95565b505050505050505050565b612c5a8282611e61565b15611533576033546001600160a01b0316638c63a1a1336040516001600160e01b031960e084901b1681526001600160a01b039182166004820152602481018690529084166044820152606401600060405180830381600087803b158015612cc157600080fd5b505af1158015612cd5573d6000803e3d6000fd5b50505050612ce03390565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600061010160019054906101000a90046001600160a01b03166001600160a01b0316634c0f38c26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111fe573d6000803e3d6000fd5b61010154604051636eb1769f60e11b81526001600160a01b03848116600483015283811660248301526000926101009004169063dd62ed3e90604401602060405180830381865afa158015612dd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e5a9190615635565b60335460405163df592f7d60e01b81526001600160a01b038381166004830152600092169063df592f7d906024016127bd565b6000612e34610d43565b9050612e3f81610dcd565b507f3fd4a614bd02c8fb908a3b3a05852476cf4c63cfc1b7280860fd956aa0982f9f612e6b81336140a4565b61010154600160a81b900460ff1615612ebb57612eb5612e8e60208501856152a9565b612e9e60408601602087016152a9565b610102546001600160a01b031660a0870135613231565b50612ee7565b612ee5612ecb60208501856152a9565b612edb60408601602087016152a9565b8560a00135613f65565b505b6001612ef960608501604086016152a9565b6001600160a01b0316612f1260408601602087016152a9565b6001600160a01b03167f49e86899b41934ffa93d6db47f37670313228803b4c819af30cd42637d84096a60a087013561293d60208901896152a9565b600061010160019054906101000a90046001600160a01b03166001600160a01b0316630db026226040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111fe573d6000803e3d6000fd5b6101015460405163f1e152df60e01b81526001600160a01b0383811660048301526000926101009004169063f1e152df906024016113ae565b6000612fe7611d77565b6033549091506001600160a01b0316634001303f336040516001600160e01b031960e084901b1681526001600160a01b0391821660048201529085166024820152604401600060405180830381600087803b15801561304557600080fd5b505af1158015613059573d6000803e3d6000fd5b50506040516001600160a01b038086169350841691507f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000610f8f825490565b6000611e5a83836141f2565b60006001600160e01b03198216637965db0b60e01b14806130e057506001600160e01b03198216635a05180f60e01b145b80610f8f57506301ffc9a760e01b6001600160e01b0319831614610f8f565b6001600160e01b03198116600090815261013260205260408120546001600160a01b031615158061314057506001600160e01b031982166301ffc9a760e01b145b80610f8f57506001600160e01b03198216639c0910f560e01b1492915050565b610101546040516306191dd160e21b815260009161010090046001600160a01b03169063186477449061319b90879087908790600401615848565b600060405180830381600087803b1580156131b557600080fd5b505af11580156131c9573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161321291815260200190565b60405180910390a35060019392505050565b60606000611e5a8361421c565b61010154604051633c6340f360e21b81526001600160a01b03868116600483015285811660248301528481166044830152606482018490526000926101009004169063f18d03cc90608401600060405180830381600087803b15801561329657600080fd5b505af11580156132aa573d6000803e3d6000fd5b505050506132b9848484613fdc565b5060015b949350505050565b603354604051633b2f4fd360e11b81526001600160a01b0383811660048301529091169063765e9fa690602401611be5565b60005b81518110156119a957826001600160a01b03166101326000848481518110613324576133246159f5565b6020908102919091018101516001600160e01b0319168252810191909152604001600020546001600160a01b0316036133bf5760006101326000848481518110613370576133706159f5565b60200260200101516001600160e01b0319166001600160e01b031916815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b6001016132fa565b60005b81518110156119a957826001600160a01b031661013160008484815181106133f4576133f46159f5565b6020908102919091018101516001600160e01b0319168252810191909152604001600020546001600160a01b03160361348f5760006101316000848481518110613440576134406159f5565b60200260200101516001600160e01b0319166001600160e01b031916815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b6001016133ca565b60005b82518110156134fd576134f4848360008685815181106134bc576134bc6159f5565b60200260200101516001600160e01b0319166001600160e01b031916815260200190815260200160002061427890919063ffffffff16565b5060010161349a565b50505050565b60006112227f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61353260c95490565b60ca546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b60606132bd848484604051806060016040528060298152602001615d696029913961428d565b604051637921219560e11b81526001600160a01b0382169063f242432a906135da90309088908b908b908a908a90600401615a0b565b600060405180830381600087803b1580156135f457600080fd5b505af1158015613608573d6000803e3d6000fd5b50505050505050505050565b61361c614368565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600054610100900460ff1661368d5760405162461bcd60e51b815260040161191a90615a46565b6136e586868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260018152603160f81b602082015291506143b19050565b6136ee886143e2565b6136fd87878787878787614422565b5050505050505050565b6001600160a01b038416600090815261012e602052604090205460ff166137415760405163a826b79f60e01b815260040160405180910390fd5b60008490506137b585826001600160a01b031663fa771d6f6040518163ffffffff1660e01b8152600401600060405180830381865afa158015613788573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526137b09190810190615a91565b6132f7565b61382485826001600160a01b031663072b88f06040518163ffffffff1660e01b8152600401600060405180830381865afa1580156137f7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261381f9190810190615a91565b6133c7565b61389685826001600160a01b031663abd9e8b26040518163ffffffff1660e01b8152600401600060405180830381865afa158015613866573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261388e9190810190615a91565b61012f613497565b61390885826001600160a01b031663fa7d91db6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156138d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139009190810190615a91565b610130613497565b6001600160a01b038516600090815261012e60205260409020805460ff19169055811561399457604051638a91b0e360e01b81526001600160a01b03821690638a91b0e39061395d9087908790600401615b2a565b600060405180830381600087803b15801561397757600080fd5b505af115801561398b573d6000803e3d6000fd5b50505050613ab6565b604051638a91b0e360e01b81526001600160a01b03821690638a91b0e3906139c29087908790600401615b2a565b600060405180830381600087803b1580156139dc57600080fd5b505af19250505080156139ed575060015b613ab6576139f9615b3e565b806308c379a003613a555750613a0d615b5a565b80613a185750613a57565b7f025a8d44fca5147c423a6a02438cb8d6356a48a281c257c915fbc4d73746228881604051613a479190614de4565b60405180910390a150613ab6565b505b3d808015613a81576040519150601f19603f3d011682016040523d82523d6000602084013e613a86565b606091505b507f025a8d44fca5147c423a6a02438cb8d6356a48a281c257c915fbc4d73746228881604051613a479190614de4565b6040516001600160a01b038616907f193a1765d1ac3f738ffc2a4803be4496d1e89ac2b4994cba4643b8d8a36eede890600090a25050505050565b6001600160a01b038316600090815261012e602052604090205460ff1615613b2c57604051636972275b60e11b815260040160405180910390fd5b6040516301ffc9a760e01b815283906001600160a01b038216906301ffc9a790613b61906350a5e2e560e01b906004016157b2565b602060405180830381865afa158015613b7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ba29190615795565b613bd557604051635fd8edab60e11b8152702737ba1024a9b4b6b83632a8363ab3b4b760791b600482015260240161191a565b613bde816144a0565b613be7816145e0565b613c5984826001600160a01b031663abd9e8b26040518163ffffffff1660e01b8152600401600060405180830381865afa158015613c29573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c519190810190615a91565b61012f614720565b613ccb84826001600160a01b031663fa7d91db6040518163ffffffff1660e01b8152600401600060405180830381865afa158015613c9b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613cc39190810190615a91565b610130614720565b6001600160a01b03808516600090815261012e602052604090819020805460ff19166001179055516306d61fe760e41b815290821690636d61fe7090613d179086908690600401615b2a565b600060405180830381600087803b158015613d3157600080fd5b505af1158015613d45573d6000803e3d6000fd5b50506040516001600160a01b03871692507f1dc3a7c7f672709e4661a9ca6b2acd21a696b4560ed2e2e4056e3b45d0f971599150600090a250505050565b6040516001600160a01b038216904780156108fc02916000818181858888f19350505050158015611533573d6000803e3d6000fd5b60405163a9059cbb60e01b81526001600160a01b0383811660048301526024820185905282169063a9059cbb906044016020604051808303816000875af1158015613e07573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134fd9190615795565b613e33614786565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586136493390565b600054610100900460ff16613e8f5760405162461bcd60e51b815260040161191a90615a46565b610101805460ff60a81b1916600160a81b8315158102919091179182905560ff91041615611a3457506101015461010280546101009092046001600160a01b03166001600160a01b0319909216919091179055565b61010154604051636361ddf360e11b815260009161010090046001600160a01b03169063c6c3bbe690613f1f90879087908790600401615848565b600060405180830381600087803b158015613f3957600080fd5b505af1158015613f4d573d6000803e3d6000fd5b50505050613f5b83836147cc565b5060019392505050565b61010154604051633dae446f60e21b815260009161010090046001600160a01b03169063f6b911bc90613fa090879087908790600401615848565b600060405180830381600087803b158015613fba57600080fd5b505af1158015613fce573d6000803e3d6000fd5b50505050613f5b83836147d8565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161402191815260200190565b60405180910390a3505050565b33600090815261012e602052604090205460609060ff166140625760405163028b1dd160e41b815260040160405180910390fd5b611e5a83838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525030939250506147e49050565b6000198214611533576033546040516377b59c2f60e11b8152600481018490526001600160a01b0383811660248301529091169063ef6b385e9060440160006040518083038186803b1580156140f957600080fd5b505afa158015611341573d6000803e3d6000fd5b604051632142170760e11b81526001600160a01b038216906342842e0e9061413d90309086908890600401615848565b600060405180830381600087803b15801561415757600080fd5b505af1158015612a53573d6000803e3d6000fd5b6001600160a01b038116600090815260fe60205260409020805490614191816001614828565b50919050565b6000610f8f6141a4613503565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000806141d688888888614845565b9250925092506141e68282614914565b50909695505050505050565b6000826000018281548110614209576142096159f5565b9060005260206000200154905092915050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561426c57602002820191906000526020600020905b815481526020019060010190808311614258575b50505050509050919050565b6000611e5a836001600160a01b0384166149cd565b6060824710156142ee5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161191a565b600080866001600160a01b0316858760405161430a9190615be3565b60006040518083038185875af1925050503d8060008114614347576040519150601f19603f3d011682016040523d82523d6000602084013e61434c565b606091505b509150915061435d87838387614ac0565b979650505050505050565b60655460ff1661183c5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161191a565b600054610100900460ff166143d85760405162461bcd60e51b815260040161191a90615a46565b6115338282614b39565b600054610100900460ff166144095760405162461bcd60e51b815260040161191a90615a46565b61441281614b7a565b61441a614baa565b611a34614bd9565b600054610100900460ff166144495760405162461bcd60e51b815260040161191a90615a46565b6101018054610100600160a81b0319166101006001600160a01b038a160217905560ff614477868883615c47565b50610100614486848683615c47565b50610101805460ff191660ff8416179055612a5381613e68565b6000816001600160a01b031663fa771d6f6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156144e0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526145089190810190615a91565b905060005b81518110156119a957600082828151811061452a5761452a6159f5565b6020908102919091018101516001600160e01b0319811660009081526101329092526040909120549091506001600160a01b0316156145a6576001600160e01b0319811660009081526101326020526040908190205490516332078b8f60e01b815261191a9183916001600160a01b0390911690600401615d06565b6001600160e01b03191660009081526101326020526040902080546001600160a01b0319166001600160a01b03851617905560010161450d565b6000816001600160a01b031663072b88f06040518163ffffffff1660e01b8152600401600060405180830381865afa158015614620573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526146489190810190615a91565b905060005b81518110156119a957600082828151811061466a5761466a6159f5565b6020908102919091018101516001600160e01b0319811660009081526101319092526040909120549091506001600160a01b0316156146e6576001600160e01b0319811660009081526101316020526040908190205490516332078b8f60e01b815261191a9183916001600160a01b0390911690600401615d06565b6001600160e01b03191660009081526101316020526040902080546001600160a01b0319166001600160a01b03851617905560010161464d565b60005b82518110156134fd5761477d84836000868581518110614745576147456159f5565b60200260200101516001600160e01b0319166001600160e01b0319168152602001908152602001600020614c0090919063ffffffff16565b50600101614723565b60655460ff161561183c5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161191a565b61153360008383613fdc565b61153382600083613fdc565b6060611e5a838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061428d565b8082600001600082825461483c9190615d29565b90915550505050565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115614880575060009150600390508261490a565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156148d4573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166149005750600092506001915082905061490a565b9250600091508190505b9450945094915050565b600082600381111561492857614928615d3c565b03614931575050565b600182600381111561494557614945615d3c565b036149635760405163f645eedf60e01b815260040160405180910390fd5b600282600381111561497757614977615d3c565b036149985760405163fce698f760e01b81526004810182905260240161191a565b60038260038111156149ac576149ac615d3c565b03611533576040516335e2f38360e21b81526004810182905260240161191a565b60008181526001830160205260408120548015614ab65760006149f16001836156d9565b8554909150600090614a05906001906156d9565b9050808214614a6a576000866000018281548110614a2557614a256159f5565b9060005260206000200154905080876000018481548110614a4857614a486159f5565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080614a7b57614a7b615d52565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610f8f565b6000915050610f8f565b60608315614b2f578251600003614b28576001600160a01b0385163b614b285760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161191a565b50816132bd565b6132bd8383614c15565b600054610100900460ff16614b605760405162461bcd60e51b815260040161191a90615a46565b81516020928301208151919092012060c99190915560ca55565b600054610100900460ff16614ba15760405162461bcd60e51b815260040161191a90615a46565b611a3481614c3f565b600054610100900460ff16614bd15760405162461bcd60e51b815260040161191a90615a46565b61183c614cdf565b600054610100900460ff1661183c5760405162461bcd60e51b815260040161191a90615a46565b6000611e5a836001600160a01b038416614d12565b815115614c255781518083602001fd5b8060405162461bcd60e51b815260040161191a9190614de4565b600054610100900460ff16614c665760405162461bcd60e51b815260040161191a90615a46565b603380546001600160a01b0319166001600160a01b038316908117909155634420e486336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015614ccb57600080fd5b505af115801561163c573d6000803e3d6000fd5b600054610100900460ff16614d065760405162461bcd60e51b815260040161191a90615a46565b6065805460ff19169055565b6000818152600183016020526040812054614d5957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610f8f565b506000610f8f565b6001600160e01b031981168114611a3457600080fd5b600060208284031215614d8957600080fd5b8135611e5a81614d61565b60005b83811015614daf578181015183820152602001614d97565b50506000910152565b60008151808452614dd0816020860160208601614d94565b601f01601f19169290920160200192915050565b602081526000611e5a6020830184614db8565b6001600160a01b0381168114611a3457600080fd5b60008060408385031215614e1f57600080fd5b8235614e2a81614df7565b946020939093013593505050565b60008151808452602080850194506020840160005b83811015614e725781516001600160a01b031687529582019590820190600101614e4d565b509495945050505050565b602080825282516001600160e01b0319168282015282015160806040830152600090614eac60a0840182614e38565b60408501516001600160a01b0316606085810191909152850151848203601f19016080860152909150614edf8282614e38565b95945050505050565b60008060408385031215614efb57600080fd5b50508035926020909101359150565b600080600060608486031215614f1f57600080fd5b8335614f2a81614df7565b92506020840135614f3a81614df7565b929592945050506040919091013590565b600060208284031215614f5d57600080fd5b5035919050565b60008060408385031215614f7757600080fd5b823591506020830135614f8981614df7565b809150509250929050565b60008083601f840112614fa657600080fd5b5081356001600160401b03811115614fbd57600080fd5b6020830191508360208260051b8501011115614fd857600080fd5b9250929050565b600080600080600060608688031215614ff757600080fd5b853561500281614df7565b945060208601356001600160401b038082111561501e57600080fd5b61502a89838a01614f94565b9096509450604088013591508082111561504357600080fd5b5061505088828901614f94565b969995985093965092949392505050565b60008083601f84011261507357600080fd5b5081356001600160401b0381111561508a57600080fd5b602083019150836020828501011115614fd857600080fd5b600080600080606085870312156150b857600080fd5b84356150c381614df7565b93506020850135925060408501356001600160401b038111156150e557600080fd5b6150f187828801615061565b95989497509550505050565b60008060008060008060a0878903121561511657600080fd5b8635955060208701359450604087013561512f81614df7565b935060608701356001600160401b0381111561514a57600080fd5b61515689828a01615061565b909450925050608087013561516a81614df7565b809150509295509295509295565b803560ff8116811461518957600080fd5b919050565b8015158114611a3457600080fd5b60008060008060008060008060c0898b0312156151b857600080fd5b88356151c381614df7565b975060208901356151d381614df7565b965060408901356001600160401b03808211156151ef57600080fd5b6151fb8c838d01615061565b909850965060608b013591508082111561521457600080fd5b506152218b828c01615061565b9095509350615234905060808a01615178565b915060a08901356152448161518e565b809150509295985092959890939650565b60008060006040848603121561526a57600080fd5b833561527581614df7565b925060208401356001600160401b0381111561529057600080fd5b61529c86828701615061565b9497909650939450505050565b6000602082840312156152bb57600080fd5b8135611e5a81614df7565b602081526000611e5a6020830184614e38565b6000806000606084860312156152ee57600080fd5b83359250602084013561530081614df7565b9150604084013561531081614df7565b809150509250925092565b60006020828403121561532d57600080fd5b8135611e5a8161518e565b6000806020838503121561534b57600080fd5b82356001600160401b0381111561536157600080fd5b61536d85828601615061565b90969095509350505050565b600060c0828403121561419157600080fd5b600080600080600080600060a0888a0312156153a657600080fd5b87356153b181614df7565b965060208801356001600160401b03808211156153cd57600080fd5b6153d98b838c01615061565b909850965060408a013591506153ee82614df7565b9094506060890135908082111561540457600080fd5b506154118a828b01615061565b90945092505060808801356154258161518e565b8091505092959891949750929550565b600080600080600080600060e0888a03121561545057600080fd5b873561545b81614df7565b9650602088013561546b81614df7565b9550604088013594506060880135935061548760808901615178565b925060a0880135915060c0880135905092959891949750929550565b600080604083850312156154b657600080fd5b82356154c181614df7565b91506020830135614f8981614df7565b6020815260008251608060208401526154ed60a0840182614db8565b905060018060a01b03602085015116604084015263ffffffff60e01b6040850151166060840152606084015160808401528091505092915050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b038111828210171561556357615563615528565b6040525050565b60006020828403121561557c57600080fd5b81516001600160401b038082111561559357600080fd5b818401915084601f8301126155a757600080fd5b8151818111156155b9576155b9615528565b60405191506155d2601f8201601f19166020018361553e565b8082528560208285010111156155e757600080fd5b6155f8816020840160208601614d94565b50949350505050565b600181811c9082168061561557607f821691505b60208210810361419157634e487b7160e01b600052602260045260246000fd5b60006020828403121561564757600080fd5b5051919050565b60006020828403121561566057600080fd5b8151611e5a81614df7565b6000808585111561567b57600080fd5b8386111561568857600080fd5b5050820193919092039150565b6001600160e01b031981358181169160048510156111a05760049490940360031b84901b1690921692915050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610f8f57610f8f6156c3565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038516815283602082015260606040820152600061573d6060830184866156ec565b9695505050505050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6000602082840312156157a757600080fd5b8151611e5a8161518e565b6001600160e01b031991909116815260200190565b600080600080608085870312156157dd57600080fd5b84356157e881614df7565b935060208501356157f881614df7565b9250604085013561580881614df7565b9396929550929360600135925050565b60008060006060848603121561582d57600080fd5b833561583881614df7565b9250602084013561530081614df7565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600080600080600060a0868803121561588457600080fd5b853561588f81614df7565b9450602086013561589f81614df7565b935060408601356158af81614df7565b94979396509394606081013594506080013592915050565b6000826158e457634e487b7160e01b600052601260045260246000fd5b500690565b60006001600160401b0382111561590257615902615528565b5060051b60200190565b60008060006060848603121561592157600080fd5b833561592c81614df7565b9250602084810135925060408501356001600160401b0381111561594f57600080fd5b8501601f8101871361596057600080fd5b803561596b816158e9565b604051615978828261553e565b82815260059290921b830184019184810191508983111561599857600080fd5b928401925b828410156159bf5783356159b081614df7565b8252928401929084019061599d565b80955050505050509250925092565b60018060a01b0384168152826020820152606060408201526000614edf6060830184614e38565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03878116825286166020820152604081018590526060810184905260a06080820181905260009061174890830184866156ec565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60006020808385031215615aa457600080fd5b82516001600160401b03811115615aba57600080fd5b8301601f81018513615acb57600080fd5b8051615ad6816158e9565b604051615ae3828261553e565b82815260059290921b8301840191848101915087831115615b0357600080fd5b928401925b8284101561435d578351615b1b81614d61565b82529284019290840190615b08565b6020815260006132bd6020830184866156ec565b600060033d1115615b575760046000803e5060005160e01c5b90565b600060443d1015615b685790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715615b9757505050505090565b8285019150815181811115615baf5750505050505090565b843d8701016020828501011115615bc95750505050505090565b615bd86020828601018761553e565b509095945050505050565b60008251615bf5818460208701614d94565b9190910192915050565b601f8211156119a9576000816000526020600020601f850160051c81016020861015615c285750805b601f850160051c820191505b8181101561134157828155600101615c34565b6001600160401b03831115615c5e57615c5e615528565b615c7283615c6c8354615601565b83615bff565b6000601f841160018114615ca65760008515615c8e5750838201355b600019600387901b1c1916600186901b17835561163c565b600083815260209020601f19861690835b82811015615cd75786850135825560209485019460019092019101615cb7565b5086821015615cf45760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6001600160e01b03199290921682526001600160a01b0316602082015260400190565b80820180821115610f8f57610f8f6156c3565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fdfe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a264697066735822122066590ac71bd682829c704720de8970bced0bc5eac2c9e9532da134102c27d5b364736f6c63430008180033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.