Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60e06040 | 15394700 | 774 days ago | IN | 0 ETH | 0.00628756 |
Latest 23 internal transactions
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
HookERC721VaultFactory
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // ██████████████ ██████████████ // ██████████████ ▄▄████████████████▄▄ ▐█████████████▌ // ██████████████ ▄█████████████████████████████▄ ██████████████ // ██████████▀ ▄█████████████████████████████████ ██████████████▌ // ██████▀ ▄██████████████████████████████████▀ ▄███████████████ // ███▀ ██████████████████████████████████▀ ▄████████████████ // ▀▀ ████████████████████████████████▀▀ ▄█████████████████▌ // █████████████████████▀▀▀▀▀▀▀ ▄▄███████████████████▀ // ██████████████████▀ ▄▄▄█████████████████████████████▀ // ████████████████▀ ▄█████████████████████████████████▀ ██▄ // ▐███████████████▀ ▄██████████████████████████████████▀ █████▄ // ██████████████▀ ▄█████████████████████████████████▀ ▄████████ // ██████████████▀ ███████████████████████████████▀ ▄████████████ // ▐█████████████▌ ▀▀▀▀████████████████████▀▀▀▀ █████████████▌ // ██████████████ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ pragma solidity ^0.8.10; import "@openzeppelin/contracts/utils/Create2.sol"; import "./HookBeaconProxy.sol"; import "./interfaces/IHookERC721VaultFactory.sol"; import "./interfaces/IHookERC721Vault.sol"; import "./interfaces/IHookProtocol.sol"; import "./interfaces/IInitializeableBeacon.sol"; import "./mixin/PermissionConstants.sol"; import "./lib/BeaconSalts.sol"; /// @title Hook Vault Factory /// @author Jake [email protected] /// @dev See {IHookERC721VaultFactory}. /// @dev The factory itself is non-upgradeable; however, each vault is upgradeable (i.e. all vaults) /// created by this factory can be upgraded at one time via the beacon pattern. contract HookERC721VaultFactory is IHookERC721VaultFactory, PermissionConstants { /// @notice Registry of all of the active vaults within the protocol, allowing users to find vaults by /// project address and tokenId; /// @dev From this view, we do not know if a vault is empty or full mapping(address => mapping(uint256 => IHookERC721Vault)) public override getVault; /// @notice Registry of all of the active multi-vaults within the protocol mapping(address => IHookERC721Vault) public override getMultiVault; address private immutable _hookProtocol; address private immutable _beacon; address private immutable _multiBeacon; constructor( address hookProtocolAddress, address beaconAddress, address multiBeaconAddress ) { require( Address.isContract(hookProtocolAddress), "hook protocol must be a contract" ); require( Address.isContract(beaconAddress), "beacon address must be a contract" ); require( Address.isContract(multiBeaconAddress), "multi beacon address must be a contract" ); _hookProtocol = hookProtocolAddress; _beacon = beaconAddress; _multiBeacon = multiBeaconAddress; } /// @notice See {IHookERC721VaultFactory-makeMultiVault}. function makeMultiVault(address nftAddress) external returns (IHookERC721Vault) { require( IHookProtocol(_hookProtocol).hasRole(ALLOWLISTER_ROLE, msg.sender) || IHookProtocol(_hookProtocol).hasRole(ALLOWLISTER_ROLE, address(0)), "makeMultiVault-Only accounts with the ALLOWLISTER role can make new multiVaults" ); require( getMultiVault[nftAddress] == IHookERC721Vault(address(0)), "makeMultiVault-vault cannot already exist" ); IInitializeableBeacon bp = IInitializeableBeacon( Create2.deploy( 0, BeaconSalts.multiVaultSalt(nftAddress), type(HookBeaconProxy).creationCode ) ); bp.initializeBeacon( _multiBeacon, /// This is the ABI encoded initializer on the IHookERC721Vault.sol abi.encodeWithSignature( "initialize(address,address)", nftAddress, _hookProtocol ) ); IHookERC721Vault vault = IHookERC721Vault(address(bp)); getMultiVault[nftAddress] = vault; emit ERC721MultiVaultCreated(nftAddress, address(bp)); return vault; } /// @notice See {IHookERC721VaultFactory-makeSoloVault}. function makeSoloVault(address nftAddress, uint256 tokenId) public override returns (IHookERC721Vault) { require( getVault[nftAddress][tokenId] == IHookERC721Vault(address(0)), "makeVault-a vault cannot already exist" ); IInitializeableBeacon bp = IInitializeableBeacon( Create2.deploy( 0, BeaconSalts.soloVaultSalt(nftAddress, tokenId), type(HookBeaconProxy).creationCode ) ); bp.initializeBeacon( _beacon, /// This is the ABI encoded initializer on the IHookERC721MultiVault.sol abi.encodeWithSignature( "initialize(address,uint256,address)", nftAddress, tokenId, _hookProtocol ) ); IHookERC721Vault vault = IHookERC721Vault(address(bp)); getVault[nftAddress][tokenId] = vault; emit ERC721VaultCreated(nftAddress, tokenId, address(vault)); return vault; } /// @notice See {IHookERC721VaultFactory-findOrCreateVault}. function findOrCreateVault(address nftAddress, uint256 tokenId) external returns (IHookERC721Vault) { if (getMultiVault[nftAddress] != IHookERC721Vault(address(0))) { return getMultiVault[nftAddress]; } if (getVault[nftAddress][tokenId] != IHookERC721Vault(address(0))) { return getVault[nftAddress][tokenId]; } return makeSoloVault(nftAddress, tokenId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @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. * * _Available since v3.1._ */ 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 `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967Upgrade { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall( address newImplementation, bytes memory data, bool forceCall ) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS( address newImplementation, bytes memory data, bool forceCall ) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Emitted when the beacon is upgraded. */ event BeaconUpgraded(address indexed beacon); /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall( address newBeacon, bytes memory data, bool forceCall ) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol) pragma solidity ^0.8.0; /** * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to * be specified by overriding the virtual {_implementation} function. * * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a * different contract through the {_delegate} function. * * The success and return data of the delegated call will be returned back to the caller of the proxy. */ abstract contract Proxy { /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _delegate(address implementation) internal virtual { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function * and {_fallback} should delegate. */ function _implementation() internal view virtual returns (address); /** * @dev Delegates the current call to the address returned by `_implementation()`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _fallback() internal virtual { _beforeFallback(); _delegate(_implementation()); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback() external payable virtual { _fallback(); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data * is empty. */ receive() external payable virtual { _fallback(); } /** * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` * call, or as part of the Solidity `fallback` or `receive` functions. * * If overridden should call `super._beforeFallback()`. */ function _beforeFallback() internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Create2.sol) pragma solidity ^0.8.0; /** * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer. * `CREATE2` can be used to compute in advance the address where a smart * contract will be deployed, which allows for interesting new mechanisms known * as 'counterfactual interactions'. * * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more * information. */ library Create2 { /** * @dev Deploys a contract using `CREATE2`. The address where the contract * will be deployed can be known in advance via {computeAddress}. * * The bytecode for a contract can be obtained from Solidity with * `type(contractName).creationCode`. * * Requirements: * * - `bytecode` must not be empty. * - `salt` must have not been used for `bytecode` already. * - the factory must have a balance of at least `amount`. * - if `amount` is non-zero, `bytecode` must have a `payable` constructor. */ function deploy( uint256 amount, bytes32 salt, bytes memory bytecode ) internal returns (address) { address addr; require(address(this).balance >= amount, "Create2: insufficient balance"); require(bytecode.length != 0, "Create2: bytecode length is zero"); assembly { addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt) } require(addr != address(0), "Create2: Failed on deploy"); return addr; } /** * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the * `bytecodeHash` or `salt` will result in a new destination address. */ function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) { return computeAddress(salt, bytecodeHash, address(this)); } /** * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}. */ function computeAddress( bytes32 salt, bytes32 bytecodeHash, address deployer ) internal pure returns (address) { bytes32 _data = keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)); return address(uint160(uint256(_data))); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol) pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ``` * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { assembly { r.slot := slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // Modified version of : OpenZeppelin Contracts v4.4.1 (proxy/beacon/BeaconProxy.sol) pragma solidity ^0.8.0; import "@openzeppelin/contracts/proxy/beacon/IBeacon.sol"; import "@openzeppelin/contracts/proxy/Proxy.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol"; /// @title HookBeaconProxy a proxy contract that points to an implementation provided by a Beacon /// @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}. /// /// The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't /// conflict with the storage layout of the implementation behind the proxy. /// /// This is an extension of the OpenZeppelin beacon proxy, however differs in that it is initializeable, which means /// it is usable with Create2. contract HookBeaconProxy is Proxy, ERC1967Upgrade { /// @dev The constructor is empty in this case because the proxy is initializeable constructor() {} bytes32 constant _INITIALIZED_SLOT = bytes32(uint256(keccak256("initializeable.beacon.version")) - 1); bytes32 constant _INITIALIZING_SLOT = bytes32(uint256(keccak256("initializeable.beacon.initializing")) - 1); /// /// @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. Equivalent to `reinitializer(1)`. modifier initializer() { bool isTopLevelCall = _setInitializedVersion(1); if (isTopLevelCall) { StorageSlot.getBooleanSlot(_INITIALIZING_SLOT).value = true; } _; if (isTopLevelCall) { StorageSlot.getBooleanSlot(_INITIALIZING_SLOT).value = false; emit Initialized(1); } } function _setInitializedVersion(uint8 version) private returns (bool) { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level // of initializers, because in other contexts the contract may have been reentered. if (StorageSlot.getBooleanSlot(_INITIALIZING_SLOT).value) { require( version == 1 && !Address.isContract(address(this)), "contract is already initialized" ); return false; } else { require( StorageSlot.getUint256Slot(_INITIALIZED_SLOT).value < version, "contract is already initialized" ); StorageSlot.getUint256Slot(_INITIALIZED_SLOT).value = version; return true; } } /// @dev Initializes the proxy with `beacon`. /// /// If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This /// will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity /// constructor. /// /// Requirements: /// ///- `beacon` must be a contract with the interface {IBeacon}. /// function initializeBeacon(address beacon, bytes memory data) public initializer { assert( _BEACON_SLOT == bytes32(uint256(keccak256("eip1967.proxy.beacon")) - 1) ); _upgradeBeaconToAndCall(beacon, data, false); } /// /// @dev Returns the current implementation address of the associated beacon. /// function _implementation() internal view virtual override returns (address) { return IBeacon(_getBeacon()).implementation(); } }
// SPDX-License-Identifier: MIT // // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // ██████████████ ██████████████ // ██████████████ ▄▄████████████████▄▄ ▐█████████████▌ // ██████████████ ▄█████████████████████████████▄ ██████████████ // ██████████▀ ▄█████████████████████████████████ ██████████████▌ // ██████▀ ▄██████████████████████████████████▀ ▄███████████████ // ███▀ ██████████████████████████████████▀ ▄████████████████ // ▀▀ ████████████████████████████████▀▀ ▄█████████████████▌ // █████████████████████▀▀▀▀▀▀▀ ▄▄███████████████████▀ // ██████████████████▀ ▄▄▄█████████████████████████████▀ // ████████████████▀ ▄█████████████████████████████████▀ ██▄ // ▐███████████████▀ ▄██████████████████████████████████▀ █████▄ // ██████████████▀ ▄█████████████████████████████████▀ ▄████████ // ██████████████▀ ███████████████████████████████▀ ▄████████████ // ▐█████████████▌ ▀▀▀▀████████████████████▀▀▀▀ █████████████▌ // ██████████████ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ pragma solidity ^0.8.10; import "./IHookVault.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; /// @title Hook ERC-721 Vault interface /// @author Jake [email protected] /// @custom:coauthor Regynald [email protected] /// /// @dev the IHookERC721 vault is an extension of the standard IHookVault /// specifically designed to hold and receive ERC721 Tokens. /// /// FLASH LOAN - /// (1) beneficial owners are able to borrow the vaulted asset for a single function call /// (2) to borrow the asset, they must implement and deploy a {IERC721FlashLoanReceiver} /// contract, and then call the flashLoan method. /// (3) At the end of the flashLoan, we ensure the asset is still owned by the vault. interface IHookERC721Vault is IHookVault, IERC721Receiver { /// @notice emitted after an asset is flash loaned by its beneficial owner. /// @dev only one asset can be flash loaned at a time, and that asset is /// denoted by the tokenId emitted. event AssetFlashLoaned(address owner, uint256 tokenId, address flashLoanImpl); /// @notice the tokenID of the underlying ERC721 token; function assetTokenId(uint32 assetId) external view returns (uint256); /// @notice flashLoans the vaulted asset to another contract for use and return to the vault. Only the owner /// may perform the flashloan /// @dev the flashloan receiver can perform arbitrary logic, but must approve the vault as an operator /// before returning. /// @param receiverAddress the contract which implements the {IERC721FlashLoanReceiver} interface to utilize the /// asset while it is loaned out /// @param params calldata params to forward to the receiver function flashLoan( uint32 assetId, address receiverAddress, bytes calldata params ) external; }
// SPDX-License-Identifier: MIT // // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // ██████████████ ██████████████ // ██████████████ ▄▄████████████████▄▄ ▐█████████████▌ // ██████████████ ▄█████████████████████████████▄ ██████████████ // ██████████▀ ▄█████████████████████████████████ ██████████████▌ // ██████▀ ▄██████████████████████████████████▀ ▄███████████████ // ███▀ ██████████████████████████████████▀ ▄████████████████ // ▀▀ ████████████████████████████████▀▀ ▄█████████████████▌ // █████████████████████▀▀▀▀▀▀▀ ▄▄███████████████████▀ // ██████████████████▀ ▄▄▄█████████████████████████████▀ // ████████████████▀ ▄█████████████████████████████████▀ ██▄ // ▐███████████████▀ ▄██████████████████████████████████▀ █████▄ // ██████████████▀ ▄█████████████████████████████████▀ ▄████████ // ██████████████▀ ███████████████████████████████▀ ▄████████████ // ▐█████████████▌ ▀▀▀▀████████████████████▀▀▀▀ █████████████▌ // ██████████████ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ pragma solidity ^0.8.10; import "./IHookERC721Vault.sol"; /// @title HookERC721Factory-factory for instances of the hook vault /// @author Jake [email protected] /// @custom:coauthor Regynald [email protected] /// /// @notice The Factory creates a specific vault for ERC721s. interface IHookERC721VaultFactory { event ERC721VaultCreated( address nftAddress, uint256 tokenId, address vaultAddress ); /// @notice emitted when a new MultiVault is deployed by the protocol /// @param nftAddress the address of the nft contract that may be deposited into the new vault /// @param vaultAddress address of the newly deployed vault event ERC721MultiVaultCreated(address nftAddress, address vaultAddress); /// @notice gets the address of a vault for a particular ERC-721 token /// @param nftAddress the contract address for the ERC-721 /// @param tokenId the tokenId for the ERC-721 /// @return the address of a {IERC721Vault} if one exists that supports the particular ERC-721, or the null address otherwise function getVault(address nftAddress, uint256 tokenId) external view returns (IHookERC721Vault); /// @notice gets the address of a multi-asset vault for a particular ERC-721 contract, if one exists /// @param nftAddress the contract address for the ERC-721 /// @return the address of the {IERC721Vault} multi asset vault, or the null address if one does not exist function getMultiVault(address nftAddress) external view returns (IHookERC721Vault); /// @notice deploy a multi-asset vault if one has not already been deployed /// @param nftAddress the contract address for the ERC-721 to be supported by the vault /// @return the address of the newly deployed {IERC721Vault} multi asset vault function makeMultiVault(address nftAddress) external returns (IHookERC721Vault); /// @notice creates a vault for a specific tokenId. If there /// is a multi-vault in existence which supports that address /// the address for that vault is returned as a new one /// does not need to be made. /// @param nftAddress the contract address for the ERC-721 /// @param tokenId the tokenId for the ERC-721 function findOrCreateVault(address nftAddress, uint256 tokenId) external returns (IHookERC721Vault); /// @notice make a new vault that can contain a single asset only /// @dev the only valid asset id in this vault is = 0 /// @param nftAddress the address of the underlying nft contract /// @param tokenId the individual token that can be deposited into this vault function makeSoloVault(address nftAddress, uint256 tokenId) external returns (IHookERC721Vault); }
// SPDX-License-Identifier: MIT // // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // ██████████████ ██████████████ // ██████████████ ▄▄████████████████▄▄ ▐█████████████▌ // ██████████████ ▄█████████████████████████████▄ ██████████████ // ██████████▀ ▄█████████████████████████████████ ██████████████▌ // ██████▀ ▄██████████████████████████████████▀ ▄███████████████ // ███▀ ██████████████████████████████████▀ ▄████████████████ // ▀▀ ████████████████████████████████▀▀ ▄█████████████████▌ // █████████████████████▀▀▀▀▀▀▀ ▄▄███████████████████▀ // ██████████████████▀ ▄▄▄█████████████████████████████▀ // ████████████████▀ ▄█████████████████████████████████▀ ██▄ // ▐███████████████▀ ▄██████████████████████████████████▀ █████▄ // ██████████████▀ ▄█████████████████████████████████▀ ▄████████ // ██████████████▀ ███████████████████████████████▀ ▄████████████ // ▐█████████████▌ ▀▀▀▀████████████████████▀▀▀▀ █████████████▌ // ██████████████ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ pragma solidity ^0.8.10; import "@openzeppelin/contracts/access/IAccessControl.sol"; /// @title HookProtocol configuration and access control repository /// @author Jake [email protected] /// @custom:coauthor Regynald [email protected] /// /// @dev it is critically important that the particular protocol implementation /// is correct as, if it is not, all assets contained within protocol contracts /// can be easily compromised. interface IHookProtocol is IAccessControl { /// @notice the address of the deployed CoveredCallFactory used by the protocol function coveredCallContract() external view returns (address); /// @notice the address of the deployed VaultFactory used by the protocol function vaultContract() external view returns (address); /// @notice callable function that reverts when the protocol is paused function throwWhenPaused() external; /// @notice the standard weth address on this chain /// @dev these are values for popular chains: /// mainnet: 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 /// kovan: 0xd0a1e359811322d97991e03f863a0c30c2cf029c /// ropsten: 0xc778417e063141139fce010982780140aa0cd5ab /// rinkeby: 0xc778417e063141139fce010982780140aa0cd5ab /// @return the weth address function getWETHAddress() external view returns (address); /// @notice get a configuration flag with a specific key for a collection /// @param collectionAddress the collection for which to lookup a configuration flag /// @param conf the config identifier for the configuration flag /// @return the true or false value of the config function getCollectionConfig(address collectionAddress, bytes32 conf) external view returns (bool); }
// SPDX-License-Identifier: MIT // // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // ██████████████ ██████████████ // ██████████████ ▄▄████████████████▄▄ ▐█████████████▌ // ██████████████ ▄█████████████████████████████▄ ██████████████ // ██████████▀ ▄█████████████████████████████████ ██████████████▌ // ██████▀ ▄██████████████████████████████████▀ ▄███████████████ // ███▀ ██████████████████████████████████▀ ▄████████████████ // ▀▀ ████████████████████████████████▀▀ ▄█████████████████▌ // █████████████████████▀▀▀▀▀▀▀ ▄▄███████████████████▀ // ██████████████████▀ ▄▄▄█████████████████████████████▀ // ████████████████▀ ▄█████████████████████████████████▀ ██▄ // ▐███████████████▀ ▄██████████████████████████████████▀ █████▄ // ██████████████▀ ▄█████████████████████████████████▀ ▄████████ // ██████████████▀ ███████████████████████████████▀ ▄████████████ // ▐█████████████▌ ▀▀▀▀████████████████████▀▀▀▀ █████████████▌ // ██████████████ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ pragma solidity ^0.8.10; import "../lib/Entitlements.sol"; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /// @title Generic Hook Vault-a vault designed to contain a single asset to be used as escrow. /// @author Jake [email protected] /// @custom:coauthor Regynald [email protected] /// /// @notice The Vault holds an asset on behalf of the owner. The owner is able to post this /// asset as collateral to other protocols by signing a message, called an "entitlement", that gives /// a specific account the ability to change the owner. /// /// The vault can work with multiple assets via the assetId, where the asset or set of assets covered by /// each segment is granted an individual id. /// Every asset must be identified by an assetId to comply with this interface, even if the vault only contains /// one asset. /// /// ENTITLEMENTS - /// (1) only one entitlement can be placed at a time. /// (2) entitlements must expire, but can also be cleared by the entitled party /// (3) if an entitlement expires, the current beneficial owner gains immediate sole control over the /// asset /// (4) the entitled entity can modify the beneficial owner of the asset, but cannot withdrawal. /// (5) the beneficial owner cannot modify the beneficial owner while an entitlement is in place /// interface IHookVault is IERC165 { /// @notice emitted when an entitlement is placed on an asset event EntitlementImposed( uint32 assetId, address entitledAccount, uint32 expiry, address beneficialOwner ); /// @notice emitted when an entitlement is cleared from an asset event EntitlementCleared(uint256 assetId, address beneficialOwner); /// @notice emitted when the beneficial owner of an asset changes /// @dev it is not required that this event is emitted when an entitlement is /// imposed that also modifies the beneficial owner. event BeneficialOwnerSet( uint32 assetId, address beneficialOwner, address setBy ); /// @notice emitted when an asset is added into the vault event AssetReceived( address owner, address sender, address contractAddress, uint32 assetId ); /// @notice Emitted when `beneficialOwner` enables `approved` to manage the `assetId` asset. event Approval( address indexed beneficialOwner, address indexed approved, uint32 indexed assetId ); /// @notice emitted when an asset is withdrawn from the vault event AssetWithdrawn(uint32 assetId, address to, address beneficialOwner); /// @notice Withdrawal an unencumbered asset from this vault /// @param assetId the asset to remove from the vault function withdrawalAsset(uint32 assetId) external; /// @notice setBeneficialOwner updates the current address that can claim the asset when it is free of entitlements. /// @param assetId the id of the subject asset to impose the entitlement /// @param newBeneficialOwner the account of the person who is able to withdrawal when there are no entitlements. function setBeneficialOwner(uint32 assetId, address newBeneficialOwner) external; /// @notice Add an entitlement claim to the asset held within the contract /// @param operator the operator to entitle /// @param expiry the duration of the entitlement /// @param assetId the id of the asset within the vault /// @param v sig v /// @param r sig r /// @param s sig s function imposeEntitlement( address operator, uint32 expiry, uint32 assetId, uint8 v, bytes32 r, bytes32 s ) external; /// @notice Allows the beneficial owner to grant an entitlement to an asset within the contract /// @dev this function call is signed by the sender per the EVM, so we know the entitlement is authentic /// @param entitlement The entitlement to impose onto the contract function grantEntitlement(Entitlements.Entitlement calldata entitlement) external; /// @notice Allows the entitled address to release their claim on the asset /// @param assetId the id of the asset to clear function clearEntitlement(uint32 assetId) external; /// @notice Removes the active entitlement from a vault and returns the asset to the beneficial owner /// @param receiver the intended receiver of the asset /// @param assetId the Id of the asset to clear function clearEntitlementAndDistribute(uint32 assetId, address receiver) external; /// @notice looks up the current beneficial owner of the asset /// @param assetId the referenced asset /// @return the address of the beneficial owner of the asset function getBeneficialOwner(uint32 assetId) external view returns (address); /// @notice checks if the asset is currently stored in the vault /// @param assetId the referenced asset /// @return true if the asset is currently within the vault, false otherwise function getHoldsAsset(uint32 assetId) external view returns (bool); /// @notice the contract address of the vaulted asset /// @param assetId the referenced asset /// @return the contract address of the vaulted asset function assetAddress(uint32 assetId) external view returns (address); /// @notice looks up the current operator of an entitlement on an asset /// @param assetId the id of the underlying asset function getCurrentEntitlementOperator(uint32 assetId) external view returns (bool, address); /// @notice Looks up the expiration timestamp of the current entitlement /// @dev returns the 0 if no entitlement is set /// @return the block timestamp after which the entitlement expires function entitlementExpiration(uint32 assetId) external view returns (uint32); /// @notice Gives permission to `to` to impose an entitlement upon `assetId` /// /// @dev Only a single account can be approved at a time, so approving the zero address clears previous approvals. /// * Requirements: /// /// - The caller must be the beneficial owner /// - `tokenId` must exist. /// /// Emits an {Approval} event. function approveOperator(address to, uint32 assetId) external; /// @dev Returns the account approved for `tokenId` token. /// /// Requirements: /// /// - `assetId` must exist. /// function getApprovedOperator(uint32 assetId) external view returns (address); }
// SPDX-License-Identifier: MIT // // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // ██████████████ ██████████████ // ██████████████ ▄▄████████████████▄▄ ▐█████████████▌ // ██████████████ ▄█████████████████████████████▄ ██████████████ // ██████████▀ ▄█████████████████████████████████ ██████████████▌ // ██████▀ ▄██████████████████████████████████▀ ▄███████████████ // ███▀ ██████████████████████████████████▀ ▄████████████████ // ▀▀ ████████████████████████████████▀▀ ▄█████████████████▌ // █████████████████████▀▀▀▀▀▀▀ ▄▄███████████████████▀ // ██████████████████▀ ▄▄▄█████████████████████████████▀ // ████████████████▀ ▄█████████████████████████████████▀ ██▄ // ▐███████████████▀ ▄██████████████████████████████████▀ █████▄ // ██████████████▀ ▄█████████████████████████████████▀ ▄████████ // ██████████████▀ ███████████████████████████████▀ ▄████████████ // ▐█████████████▌ ▀▀▀▀████████████████████▀▀▀▀ █████████████▌ // ██████████████ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ pragma solidity ^0.8.10; /// @title Interface for a beacon with an initializer function /// @author Jake [email protected] /// @custom:coauthor Regynald [email protected] /// /// @dev the Hook Beacons conform to this interface, and can be called /// with this initializer in order to start a beacon interface IInitializeableBeacon { function initializeBeacon(address beacon, bytes memory data) external; }
// SPDX-License-Identifier: MIT // // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // ██████████████ ██████████████ // ██████████████ ▄▄████████████████▄▄ ▐█████████████▌ // ██████████████ ▄█████████████████████████████▄ ██████████████ // ██████████▀ ▄█████████████████████████████████ ██████████████▌ // ██████▀ ▄██████████████████████████████████▀ ▄███████████████ // ███▀ ██████████████████████████████████▀ ▄████████████████ // ▀▀ ████████████████████████████████▀▀ ▄█████████████████▌ // █████████████████████▀▀▀▀▀▀▀ ▄▄███████████████████▀ // ██████████████████▀ ▄▄▄█████████████████████████████▀ // ████████████████▀ ▄█████████████████████████████████▀ ██▄ // ▐███████████████▀ ▄██████████████████████████████████▀ █████▄ // ██████████████▀ ▄█████████████████████████████████▀ ▄████████ // ██████████████▀ ███████████████████████████████▀ ▄████████████ // ▐█████████████▌ ▀▀▀▀████████████████████▀▀▀▀ █████████████▌ // ██████████████ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ pragma solidity ^0.8.10; import "../HookBeaconProxy.sol"; library BeaconSalts { // keep functions internal to prevent the need for library linking // and to reduce gas costs bytes32 internal constant ByteCodeHash = keccak256(type(HookBeaconProxy).creationCode); function soloVaultSalt(address nftAddress, uint256 tokenId) internal pure returns (bytes32) { return keccak256(abi.encode(nftAddress, tokenId)); } function multiVaultSalt(address nftAddress) internal pure returns (bytes32) { return keccak256(abi.encode(nftAddress)); } }
// SPDX-License-Identifier: MIT // // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // ██████████████ ██████████████ // ██████████████ ▄▄████████████████▄▄ ▐█████████████▌ // ██████████████ ▄█████████████████████████████▄ ██████████████ // ██████████▀ ▄█████████████████████████████████ ██████████████▌ // ██████▀ ▄██████████████████████████████████▀ ▄███████████████ // ███▀ ██████████████████████████████████▀ ▄████████████████ // ▀▀ ████████████████████████████████▀▀ ▄█████████████████▌ // █████████████████████▀▀▀▀▀▀▀ ▄▄███████████████████▀ // ██████████████████▀ ▄▄▄█████████████████████████████▀ // ████████████████▀ ▄█████████████████████████████████▀ ██▄ // ▐███████████████▀ ▄██████████████████████████████████▀ █████▄ // ██████████████▀ ▄█████████████████████████████████▀ ▄████████ // ██████████████▀ ███████████████████████████████▀ ▄████████████ // ▐█████████████▌ ▀▀▀▀████████████████████▀▀▀▀ █████████████▌ // ██████████████ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ pragma solidity ^0.8.10; import "./Signatures.sol"; library Entitlements { uint256 private constant _ENTITLEMENT_TYPEHASH = uint256( keccak256( abi.encodePacked( "Entitlement(", "address beneficialOwner,", "address operator,", "address vaultAddress,", "uint32 assetId,", "uint32 expiry", ")" ) ) ); /// ---- STRUCTS ----- struct Entitlement { /// @notice the beneficial owner address this entitlement applies to. This address will also be the signer. address beneficialOwner; /// @notice the operating contract that can change ownership during the entitlement period. address operator; /// @notice the contract address for the vault that contains the underlying assets address vaultAddress; /// @notice the assetId of the asset or assets within the vault uint32 assetId; /// @notice the block timestamp after which the asset is free of the entitlement uint32 expiry; } function getEntitlementStructHash(Entitlement memory entitlement) internal pure returns (bytes32) { // TODO: Hash in place to save gas. return keccak256( abi.encode( _ENTITLEMENT_TYPEHASH, entitlement.beneficialOwner, entitlement.operator, entitlement.vaultAddress, entitlement.assetId, entitlement.expiry ) ); } }
// SPDX-License-Identifier: MIT // // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // ██████████████ ██████████████ // ██████████████ ▄▄████████████████▄▄ ▐█████████████▌ // ██████████████ ▄█████████████████████████████▄ ██████████████ // ██████████▀ ▄█████████████████████████████████ ██████████████▌ // ██████▀ ▄██████████████████████████████████▀ ▄███████████████ // ███▀ ██████████████████████████████████▀ ▄████████████████ // ▀▀ ████████████████████████████████▀▀ ▄█████████████████▌ // █████████████████████▀▀▀▀▀▀▀ ▄▄███████████████████▀ // ██████████████████▀ ▄▄▄█████████████████████████████▀ // ████████████████▀ ▄█████████████████████████████████▀ ██▄ // ▐███████████████▀ ▄██████████████████████████████████▀ █████▄ // ██████████████▀ ▄█████████████████████████████████▀ ▄████████ // ██████████████▀ ███████████████████████████████▀ ▄████████████ // ▐█████████████▌ ▀▀▀▀████████████████████▀▀▀▀ █████████████▌ // ██████████████ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ pragma solidity ^0.8.10; /// @dev A library for validating signatures from ZeroEx library Signatures { /// @dev Allowed signature types. enum SignatureType { EIP712 } /// @dev Encoded EC signature. struct Signature { // How to validate the signature. SignatureType signatureType; // EC Signature data. uint8 v; // EC Signature data. bytes32 r; // EC Signature data. bytes32 s; } }
// SPDX-License-Identifier: MIT // // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // █████████████▌ ▐█████████████ // ██████████████ ██████████████ // ██████████████ ▄▄████████████████▄▄ ▐█████████████▌ // ██████████████ ▄█████████████████████████████▄ ██████████████ // ██████████▀ ▄█████████████████████████████████ ██████████████▌ // ██████▀ ▄██████████████████████████████████▀ ▄███████████████ // ███▀ ██████████████████████████████████▀ ▄████████████████ // ▀▀ ████████████████████████████████▀▀ ▄█████████████████▌ // █████████████████████▀▀▀▀▀▀▀ ▄▄███████████████████▀ // ██████████████████▀ ▄▄▄█████████████████████████████▀ // ████████████████▀ ▄█████████████████████████████████▀ ██▄ // ▐███████████████▀ ▄██████████████████████████████████▀ █████▄ // ██████████████▀ ▄█████████████████████████████████▀ ▄████████ // ██████████████▀ ███████████████████████████████▀ ▄████████████ // ▐█████████████▌ ▀▀▀▀████████████████████▀▀▀▀ █████████████▌ // ██████████████ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ // █████████████▌ ██████████████ pragma solidity ^0.8.10; /// @notice roles on the hook protocol that can be read by other contract /// @dev new roles here should be initialized in the constructor of the protocol abstract contract PermissionConstants { /// ----- ROLES -------- /// @notice the allowlister is able to enable and disable projects to mint instruments bytes32 public constant ALLOWLISTER_ROLE = keccak256("ALLOWLISTER_ROLE"); /// @notice the pauser is able to start and pause various components of the protocol bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); /// @notice the vault upgrader role is able to upgrade the implementation for all vaults bytes32 public constant VAULT_UPGRADER = keccak256("VAULT_UPGRADER"); /// @notice the call upgrader role is able to upgrade the implementation of the covered call options bytes32 public constant CALL_UPGRADER = keccak256("CALL_UPGRADER"); /// @notice the market configuration role allows the actor to make changes to how the market operates bytes32 public constant MARKET_CONF = keccak256("MARKET_CONF"); /// @notice the collection configuration role allows the actor to make changes the collection /// configs on the protocol contract bytes32 public constant COLLECTION_CONF = keccak256("COLLECTION_CONF"); }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 10 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"hookProtocolAddress","type":"address"},{"internalType":"address","name":"beaconAddress","type":"address"},{"internalType":"address","name":"multiBeaconAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":false,"internalType":"address","name":"vaultAddress","type":"address"}],"name":"ERC721MultiVaultCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"vaultAddress","type":"address"}],"name":"ERC721VaultCreated","type":"event"},{"inputs":[],"name":"ALLOWLISTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CALL_UPGRADER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COLLECTION_CONF","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MARKET_CONF","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAULT_UPGRADER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"findOrCreateVault","outputs":[{"internalType":"contract IHookERC721Vault","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getMultiVault","outputs":[{"internalType":"contract IHookERC721Vault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"getVault","outputs":[{"internalType":"contract IHookERC721Vault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"}],"name":"makeMultiVault","outputs":[{"internalType":"contract IHookERC721Vault","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"makeSoloVault","outputs":[{"internalType":"contract IHookERC721Vault","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e06040523480156200001157600080fd5b5060405162001752380380620017528339810160408190526200003491620001c8565b6200004a836200019c60201b620008cd1760201c565b6200009c5760405162461bcd60e51b815260206004820181905260248201527f686f6f6b2070726f746f636f6c206d757374206265206120636f6e747261637460448201526064015b60405180910390fd5b620000b2826200019c60201b620008cd1760201c565b6200010a5760405162461bcd60e51b815260206004820152602160248201527f626561636f6e2061646472657373206d757374206265206120636f6e747261636044820152601d60fa1b606482015260840162000093565b62000120816200019c60201b620008cd1760201c565b6200017e5760405162461bcd60e51b815260206004820152602760248201527f6d756c746920626561636f6e2061646472657373206d757374206265206120636044820152661bdb9d1c9858dd60ca1b606482015260840162000093565b6001600160a01b0392831660805290821660a0521660c05262000212565b6001600160a01b03163b151590565b80516001600160a01b0381168114620001c357600080fd5b919050565b600080600060608486031215620001de57600080fd5b620001e984620001ab565b9250620001f960208501620001ab565b91506200020960408501620001ab565b90509250925092565b60805160a05160c0516114fb6200025760003960006106e60152600061032b01526000818161034e0152818161049501528181610538015261070801526114fb6000f3fe608060405234801561001057600080fd5b50600436106100995760003560e01c80630bc0d3fa1461009e5780630d5e67ec146100c7578063435b51de146100fc5780636fe76da61461010f578063a34fd3fb14610138578063acca68381461015f578063b6f3fa3f14610174578063bb31173a14610187578063d99d13f5146101ae578063e63ab1e9146101df578063f23c19e814610206575b600080fd5b6100b16100ac366004610a3b565b61022d565b6040516100be9190610a65565b60405180910390f35b6100ee7f945438d5e976f17e0d00cb2997cf8951c55e12977d86234d6738d1865abe006e81565b6040519081526020016100be565b6100b161010a366004610a79565b61047b565b6100b161011d366004610a79565b6001602052600090815260409020546001600160a01b031681565b6100ee7f657f307dfada290937bc821a25e2da10feb07809ba9560b816723e8b47fe379a81565b6100ee6000805160206114a683398151915281565b6100b1610182366004610a3b565b610826565b6100ee7ff7e0191f3657a6da7569740b1cdeac8c3425bcbfd257d4fdc6d2241598f4de8b81565b6100b16101bc366004610a3b565b60006020818152928152604080822090935290815220546001600160a01b031681565b6100ee7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6100ee7f8de11a8d956993287a5b6a74c069984045abc1b621d651081c4c77c05c3cb7af81565b6001600160a01b03828116600090815260208181526040808320858452909152812054909116156102b45760405162461bcd60e51b815260206004820152602660248201527f6d616b655661756c742d61207661756c742063616e6e6f7420616c726561647960448201526508195e1a5cdd60d21b60648201526084015b60405180910390fd5b604080516001600160a01b038516602080830191909152818301859052825180830384018152606090920190925280519101206000906103189082905b60405161030060208201610a12565b601f1982820381018352601f909101166040526108dc565b9050806001600160a01b0316637fe8e72c7f000000000000000000000000000000000000000000000000000000000000000086867f000000000000000000000000000000000000000000000000000000000000000060405160240161037f93929190610a94565b60408051601f198184030181529181526020820180516001600160e01b031663c350a1b560e01b1790525160e084901b6001600160e01b03191681526103c9929190600401610ab7565b600060405180830381600087803b1580156103e357600080fd5b505af11580156103f7573d6000803e3d6000fd5b505050506001600160a01b038481166000908152602081815260408083208784529091529081902080546001600160a01b031916928416929092179091555181907fec1cb694178d064cbb440cc15ed37f43d60f55db3e5c1aa3b16f3da853812e579061046990879087908590610a94565b60405180910390a19150505b92915050565b604051632474521560e21b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391d14854906104da906000805160206114a6833981519152903390600401610b1c565b602060405180830381865afa1580156104f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051b9190610b33565b806105bf5750604051632474521560e21b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906391d148549061057e906000805160206114a683398151915290600090600401610b1c565b602060405180830381865afa15801561059b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105bf9190610b33565b6106495760405162461bcd60e51b815260206004820152604f60248201527f6d616b654d756c74695661756c742d4f6e6c79206163636f756e74732077697460448201527f682074686520414c4c4f574c495354455220726f6c652063616e206d616b652060648201526e6e6577206d756c74695661756c747360881b608482015260a4016102ab565b6001600160a01b0382811660009081526001602052604090205416156106c35760405162461bcd60e51b815260206004820152602960248201527f6d616b654d756c74695661756c742d7661756c742063616e6e6f7420616c726560448201526818591e48195e1a5cdd60ba1b60648201526084016102ab565b60006106d360006102f1856109e2565b9050806001600160a01b0316637fe8e72c7f0000000000000000000000000000000000000000000000000000000000000000857f0000000000000000000000000000000000000000000000000000000000000000604051602401610738929190610b55565b60408051601f198184030181529181526020820180516001600160e01b031663485cc95560e01b1790525160e084901b6001600160e01b0319168152610782929190600401610ab7565b600060405180830381600087803b15801561079c57600080fd5b505af11580156107b0573d6000803e3d6000fd5b505050506001600160a01b038381166000908152600160205260409081902080546001600160a01b031916928416929092179091555181907f4576e6da87b352d9168729d519d6b20717c930bc4aca52cd876b1c797227acc7906108179086908490610b55565b60405180910390a19392505050565b6001600160a01b038281166000908152600160205260408120549091161561086957506001600160a01b0380831660009081526001602052604090205416610475565b6001600160a01b0383811660009081526020818152604080832086845290915290205416156108bc57506001600160a01b0380831660009081526020818152604080832085845290915290205416610475565b6108c6838361022d565b9392505050565b6001600160a01b03163b151590565b6000808447101561092f5760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e636500000060448201526064016102ab565b825161097d5760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f60448201526064016102ab565b8383516020850187f590506001600160a01b0381166109da5760405162461bcd60e51b8152602060048201526019602482015278437265617465323a204661696c6564206f6e206465706c6f7960381b60448201526064016102ab565b949350505050565b6000816040516020016109f59190610a65565b604051602081830303815290604052805190602001209050919050565b61093680610b7083390190565b80356001600160a01b0381168114610a3657600080fd5b919050565b60008060408385031215610a4e57600080fd5b610a5783610a1f565b946020939093013593505050565b6001600160a01b0391909116815260200190565b600060208284031215610a8b57600080fd5b6108c682610a1f565b6001600160a01b0393841681526020810192909252909116604082015260600190565b60018060a01b038316815260006020604081840152835180604085015260005b81811015610af357858101830151858201606001528201610ad7565b81811115610b05576000606083870101525b50601f01601f191692909201606001949350505050565b9182526001600160a01b0316602082015260400190565b600060208284031215610b4557600080fd5b815180151581146108c657600080fd5b6001600160a01b039283168152911660208201526040019056fe608060405234801561001057600080fd5b50610916806100206000396000f3fe6080604052600436106100225760003560e01c80637fe8e72c1461003957610031565b366100315761002f610059565b005b61002f610059565b34801561004557600080fd5b5061002f61005436600461068c565b61006b565b61006961006461016f565b6101f6565b565b6000610077600161021a565b905080156100af57600161009f61009c8260008051602061087a83398151915261074f565b90565b805460ff19169115159190911790555b6100da60017fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5161074f565b60008051602061085a833981519152146100f6576100f6610774565b610102838360006102ee565b801561016a57600061012661009c600160008051602061087a83398151915261074f565b805460ff1916911515919091179055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600061019060008051602061085a833981519152546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101f1919061078a565b905090565b3660008037600080366000845af43d6000803e808015610215573d6000f35b3d6000fd5b600061023861009c600160008051602061087a83398151915261074f565b5460ff1615610287578160ff16600114801561025a5750610258306103ae565b155b61027f5760405162461bcd60e51b8152600401610276906107a7565b60405180910390fd5b506000919050565b60ff82166102a761009c600160008051602061089a83398151915261074f565b54106102c55760405162461bcd60e51b8152600401610276906107a7565b60ff82166102e561009c600160008051602061089a83398151915261074f565b55506001919050565b6102f7836103bd565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a26000825111806103385750805b1561016a576103a8836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561037e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a2919061078a565b8361051e565b50505050565b6001600160a01b03163b151590565b6103c6816103ae565b6104205760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b6064820152608401610276565b61048a816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610461573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610485919061078a565b6103ae565b6104ef5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610276565b60008051602061085a83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b606061054383836040518060600160405280602781526020016108ba6027913961054a565b9392505050565b6060610555846103ae565b6105b05760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610276565b600080856001600160a01b0316856040516105cb919061080a565b600060405180830381855af49150503d8060008114610606576040519150601f19603f3d011682016040523d82523d6000602084013e61060b565b606091505b509150915061061b828286610625565b9695505050505050565b60608315610634575081610543565b8251156106445782518084602001fd5b8160405162461bcd60e51b81526004016102769190610826565b6001600160a01b038116811461067357600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561069f57600080fd5b82356106aa8161065e565b915060208301356001600160401b03808211156106c657600080fd5b818501915085601f8301126106da57600080fd5b8135818111156106ec576106ec610676565b604051601f8201601f19908116603f0116810190838211818310171561071457610714610676565b8160405282815288602084870101111561072d57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60008282101561076f57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b60006020828403121561079c57600080fd5b81516105438161065e565b6020808252601f908201527f636f6e747261637420697320616c726561647920696e697469616c697a656400604082015260600190565b60005b838110156107f95781810151838201526020016107e1565b838111156103a85750506000910152565b6000825161081c8184602087016107de565b9190910192915050565b60208152600082518060208401526108458160408501602087016107de565b601f01601f1916919091016040019291505056fea3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50ba701f97ffd09be973ab0487da5ef9921c2bd0aad55202b3c0b41745a8ecda29021cb2f443fd62c4cb6b5d341f5eb8cd045222fc4183f8753d3725ac19741805416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b9160d7d2c1102ca8191ecd78f04d42a9f497feb44eb9ea5596cee55560cbe9964736f6c634300080a0033fba4f6dd992a27a814ee807eb2f9332d6d01312041726966a540cf4a4a891553a264697066735822122019be1da81becabca6aee761807b52ec3189fae2f73d55a554df96cc3f2c4f44564736f6c634300080a0033000000000000000000000000e11cced3e6555a1bcba2e19b9cf161f040186069000000000000000000000000f8d40ad159ebe0314a07e2d0d6f73a486ecf8520000000000000000000000000f70c0b90cc65aadc2a6a70fe0d86b2a05e15b85f
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100995760003560e01c80630bc0d3fa1461009e5780630d5e67ec146100c7578063435b51de146100fc5780636fe76da61461010f578063a34fd3fb14610138578063acca68381461015f578063b6f3fa3f14610174578063bb31173a14610187578063d99d13f5146101ae578063e63ab1e9146101df578063f23c19e814610206575b600080fd5b6100b16100ac366004610a3b565b61022d565b6040516100be9190610a65565b60405180910390f35b6100ee7f945438d5e976f17e0d00cb2997cf8951c55e12977d86234d6738d1865abe006e81565b6040519081526020016100be565b6100b161010a366004610a79565b61047b565b6100b161011d366004610a79565b6001602052600090815260409020546001600160a01b031681565b6100ee7f657f307dfada290937bc821a25e2da10feb07809ba9560b816723e8b47fe379a81565b6100ee6000805160206114a683398151915281565b6100b1610182366004610a3b565b610826565b6100ee7ff7e0191f3657a6da7569740b1cdeac8c3425bcbfd257d4fdc6d2241598f4de8b81565b6100b16101bc366004610a3b565b60006020818152928152604080822090935290815220546001600160a01b031681565b6100ee7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b6100ee7f8de11a8d956993287a5b6a74c069984045abc1b621d651081c4c77c05c3cb7af81565b6001600160a01b03828116600090815260208181526040808320858452909152812054909116156102b45760405162461bcd60e51b815260206004820152602660248201527f6d616b655661756c742d61207661756c742063616e6e6f7420616c726561647960448201526508195e1a5cdd60d21b60648201526084015b60405180910390fd5b604080516001600160a01b038516602080830191909152818301859052825180830384018152606090920190925280519101206000906103189082905b60405161030060208201610a12565b601f1982820381018352601f909101166040526108dc565b9050806001600160a01b0316637fe8e72c7f000000000000000000000000f8d40ad159ebe0314a07e2d0d6f73a486ecf852086867f000000000000000000000000e11cced3e6555a1bcba2e19b9cf161f04018606960405160240161037f93929190610a94565b60408051601f198184030181529181526020820180516001600160e01b031663c350a1b560e01b1790525160e084901b6001600160e01b03191681526103c9929190600401610ab7565b600060405180830381600087803b1580156103e357600080fd5b505af11580156103f7573d6000803e3d6000fd5b505050506001600160a01b038481166000908152602081815260408083208784529091529081902080546001600160a01b031916928416929092179091555181907fec1cb694178d064cbb440cc15ed37f43d60f55db3e5c1aa3b16f3da853812e579061046990879087908590610a94565b60405180910390a19150505b92915050565b604051632474521560e21b81526000906001600160a01b037f000000000000000000000000e11cced3e6555a1bcba2e19b9cf161f04018606916906391d14854906104da906000805160206114a6833981519152903390600401610b1c565b602060405180830381865afa1580156104f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051b9190610b33565b806105bf5750604051632474521560e21b81526001600160a01b037f000000000000000000000000e11cced3e6555a1bcba2e19b9cf161f04018606916906391d148549061057e906000805160206114a683398151915290600090600401610b1c565b602060405180830381865afa15801561059b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105bf9190610b33565b6106495760405162461bcd60e51b815260206004820152604f60248201527f6d616b654d756c74695661756c742d4f6e6c79206163636f756e74732077697460448201527f682074686520414c4c4f574c495354455220726f6c652063616e206d616b652060648201526e6e6577206d756c74695661756c747360881b608482015260a4016102ab565b6001600160a01b0382811660009081526001602052604090205416156106c35760405162461bcd60e51b815260206004820152602960248201527f6d616b654d756c74695661756c742d7661756c742063616e6e6f7420616c726560448201526818591e48195e1a5cdd60ba1b60648201526084016102ab565b60006106d360006102f1856109e2565b9050806001600160a01b0316637fe8e72c7f000000000000000000000000f70c0b90cc65aadc2a6a70fe0d86b2a05e15b85f857f000000000000000000000000e11cced3e6555a1bcba2e19b9cf161f040186069604051602401610738929190610b55565b60408051601f198184030181529181526020820180516001600160e01b031663485cc95560e01b1790525160e084901b6001600160e01b0319168152610782929190600401610ab7565b600060405180830381600087803b15801561079c57600080fd5b505af11580156107b0573d6000803e3d6000fd5b505050506001600160a01b038381166000908152600160205260409081902080546001600160a01b031916928416929092179091555181907f4576e6da87b352d9168729d519d6b20717c930bc4aca52cd876b1c797227acc7906108179086908490610b55565b60405180910390a19392505050565b6001600160a01b038281166000908152600160205260408120549091161561086957506001600160a01b0380831660009081526001602052604090205416610475565b6001600160a01b0383811660009081526020818152604080832086845290915290205416156108bc57506001600160a01b0380831660009081526020818152604080832085845290915290205416610475565b6108c6838361022d565b9392505050565b6001600160a01b03163b151590565b6000808447101561092f5760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e636500000060448201526064016102ab565b825161097d5760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f60448201526064016102ab565b8383516020850187f590506001600160a01b0381166109da5760405162461bcd60e51b8152602060048201526019602482015278437265617465323a204661696c6564206f6e206465706c6f7960381b60448201526064016102ab565b949350505050565b6000816040516020016109f59190610a65565b604051602081830303815290604052805190602001209050919050565b61093680610b7083390190565b80356001600160a01b0381168114610a3657600080fd5b919050565b60008060408385031215610a4e57600080fd5b610a5783610a1f565b946020939093013593505050565b6001600160a01b0391909116815260200190565b600060208284031215610a8b57600080fd5b6108c682610a1f565b6001600160a01b0393841681526020810192909252909116604082015260600190565b60018060a01b038316815260006020604081840152835180604085015260005b81811015610af357858101830151858201606001528201610ad7565b81811115610b05576000606083870101525b50601f01601f191692909201606001949350505050565b9182526001600160a01b0316602082015260400190565b600060208284031215610b4557600080fd5b815180151581146108c657600080fd5b6001600160a01b039283168152911660208201526040019056fe608060405234801561001057600080fd5b50610916806100206000396000f3fe6080604052600436106100225760003560e01c80637fe8e72c1461003957610031565b366100315761002f610059565b005b61002f610059565b34801561004557600080fd5b5061002f61005436600461068c565b61006b565b61006961006461016f565b6101f6565b565b6000610077600161021a565b905080156100af57600161009f61009c8260008051602061087a83398151915261074f565b90565b805460ff19169115159190911790555b6100da60017fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5161074f565b60008051602061085a833981519152146100f6576100f6610774565b610102838360006102ee565b801561016a57600061012661009c600160008051602061087a83398151915261074f565b805460ff1916911515919091179055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600061019060008051602061085a833981519152546001600160a01b031690565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101f1919061078a565b905090565b3660008037600080366000845af43d6000803e808015610215573d6000f35b3d6000fd5b600061023861009c600160008051602061087a83398151915261074f565b5460ff1615610287578160ff16600114801561025a5750610258306103ae565b155b61027f5760405162461bcd60e51b8152600401610276906107a7565b60405180910390fd5b506000919050565b60ff82166102a761009c600160008051602061089a83398151915261074f565b54106102c55760405162461bcd60e51b8152600401610276906107a7565b60ff82166102e561009c600160008051602061089a83398151915261074f565b55506001919050565b6102f7836103bd565b6040516001600160a01b038416907f1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e90600090a26000825111806103385750805b1561016a576103a8836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561037e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a2919061078a565b8361051e565b50505050565b6001600160a01b03163b151590565b6103c6816103ae565b6104205760405162461bcd60e51b815260206004820152602560248201527f455243313936373a206e657720626561636f6e206973206e6f74206120636f6e6044820152641d1c9858dd60da1b6064820152608401610276565b61048a816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610461573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610485919061078a565b6103ae565b6104ef5760405162461bcd60e51b815260206004820152603060248201527f455243313936373a20626561636f6e20696d706c656d656e746174696f6e206960448201526f1cc81b9bdd08184818dbdb9d1c9858dd60821b6064820152608401610276565b60008051602061085a83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b606061054383836040518060600160405280602781526020016108ba6027913961054a565b9392505050565b6060610555846103ae565b6105b05760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610276565b600080856001600160a01b0316856040516105cb919061080a565b600060405180830381855af49150503d8060008114610606576040519150601f19603f3d011682016040523d82523d6000602084013e61060b565b606091505b509150915061061b828286610625565b9695505050505050565b60608315610634575081610543565b8251156106445782518084602001fd5b8160405162461bcd60e51b81526004016102769190610826565b6001600160a01b038116811461067357600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561069f57600080fd5b82356106aa8161065e565b915060208301356001600160401b03808211156106c657600080fd5b818501915085601f8301126106da57600080fd5b8135818111156106ec576106ec610676565b604051601f8201601f19908116603f0116810190838211818310171561071457610714610676565b8160405282815288602084870101111561072d57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60008282101561076f57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b60006020828403121561079c57600080fd5b81516105438161065e565b6020808252601f908201527f636f6e747261637420697320616c726561647920696e697469616c697a656400604082015260600190565b60005b838110156107f95781810151838201526020016107e1565b838111156103a85750506000910152565b6000825161081c8184602087016107de565b9190910192915050565b60208152600082518060208401526108458160408501602087016107de565b601f01601f1916919091016040019291505056fea3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50ba701f97ffd09be973ab0487da5ef9921c2bd0aad55202b3c0b41745a8ecda29021cb2f443fd62c4cb6b5d341f5eb8cd045222fc4183f8753d3725ac19741805416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b9160d7d2c1102ca8191ecd78f04d42a9f497feb44eb9ea5596cee55560cbe9964736f6c634300080a0033fba4f6dd992a27a814ee807eb2f9332d6d01312041726966a540cf4a4a891553a264697066735822122019be1da81becabca6aee761807b52ec3189fae2f73d55a554df96cc3f2c4f44564736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e11cced3e6555a1bcba2e19b9cf161f040186069000000000000000000000000f8d40ad159ebe0314a07e2d0d6f73a486ecf8520000000000000000000000000f70c0b90cc65aadc2a6a70fe0d86b2a05e15b85f
-----Decoded View---------------
Arg [0] : hookProtocolAddress (address): 0xE11CCED3E6555A1BcbA2E19b9Cf161f040186069
Arg [1] : beaconAddress (address): 0xF8d40AD159EBE0314a07E2D0d6F73A486ECF8520
Arg [2] : multiBeaconAddress (address): 0xF70C0b90cC65AadC2A6A70fE0d86B2A05E15B85F
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000e11cced3e6555a1bcba2e19b9cf161f040186069
Arg [1] : 000000000000000000000000f8d40ad159ebe0314a07e2d0d6f73a486ecf8520
Arg [2] : 000000000000000000000000f70c0b90cc65aadc2a6a70fe0d86b2a05e15b85f
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.