Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Multi Chain
Multichain Addresses
0 address found via
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 13628523 | 564 days 15 hrs ago | IN | Create: ConcurrentCanExecFacet | 0 ETH | 0.06157305 |
Loading...
Loading
Contract Name:
ConcurrentCanExecFacet
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 {BFacetOwner} from "./base/BFacetOwner.sol"; import {LibConcurrentCanExec} from "../libraries/LibConcurrentCanExec.sol"; contract ConcurrentCanExecFacet is BFacetOwner { function setSlotLength(uint256 _slotLength) external onlyOwner { LibConcurrentCanExec.setSlotLength(_slotLength); } function slotLength() external view returns (uint256) { return LibConcurrentCanExec.slotLength(); } function concurrentCanExec(uint256 _buffer) external view returns (bool) { return LibConcurrentCanExec.concurrentCanExec(_buffer); } function getCurrentExecutorIndex() external view returns (uint256 executorIndex, uint256 remainingBlocksInSlot) { return LibConcurrentCanExec.getCurrentExecutorIndexAtBlock(block.number); } function currentExecutor() external view returns ( address executor, uint256 executorIndex, uint256 remainingBlocksInSlot ) { return LibConcurrentCanExec.currentExecutor(); } function mySlotStatus(uint256 _buffer) external view returns (LibConcurrentCanExec.SlotStatus) { return LibConcurrentCanExec.mySlotStatus(_buffer); } function calcExecutorIndex( uint256 _currentBlock, uint256 _blocksPerSlot, uint256 _numberOfExecutors ) external pure returns (uint256 executorIndex, uint256 remainingBlocksInSlot) { return LibConcurrentCanExec.calcExecutorIndex( _currentBlock, _blocksPerSlot, _numberOfExecutors ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { 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) { return _values(set._inner); } // 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; 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 on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @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; assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {LibDiamond} from "../../libraries/standard/LibDiamond.sol"; abstract contract BFacetOwner { modifier onlyOwner() { LibDiamond.enforceIsContractOwner(); _; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; /******************************************************************************\ * Author: Nick Mudge <[email protected]> (https://twitter.com/mudgen) * EIP-2535 Diamond Standard: https://eips.ethereum.org/EIPS/eip-2535 /******************************************************************************/ interface IDiamondCut { enum FacetCutAction { Add, Replace, Remove } // Add=0, Replace=1, Remove=2 struct FacetCut { address facetAddress; FacetCutAction action; bytes4[] functionSelectors; } event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata); /// @notice Add/replace/remove any number of functions and optionally execute /// a function with delegatecall /// @param _diamondCut Contains the facet addresses and function selectors /// @param _init The address of the contract or facet to execute _calldata /// @param _calldata A function call, including function selector and arguments /// _calldata is executed with delegatecall on _init function diamondCut( FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata ) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {LibExecutor} from "./LibExecutor.sol"; library LibConcurrentCanExec { using LibExecutor for address; enum SlotStatus { Open, Closing, Closed } struct ConcurrentExecStorage { uint256 slotLength; } bytes32 private constant _CONCURRENT_EXEC_STORAGE_POSITION = keccak256("gelato.diamond.concurrentexec.storage"); function setSlotLength(uint256 _slotLength) internal { concurrentExecStorage().slotLength = _slotLength; } function slotLength() internal view returns (uint256) { return concurrentExecStorage().slotLength; } function concurrentCanExec(uint256 _buffer) internal view returns (bool) { return msg.sender.canExec() && LibExecutor.numberOfExecutors() == 1 ? true : mySlotStatus(_buffer) == LibConcurrentCanExec.SlotStatus.Open; } function getCurrentExecutorIndexAtBlock(uint256 _currentBlock) internal view returns (uint256 executorIndex, uint256 remainingBlocksInSlot) { uint256 numberOfExecutors = LibExecutor.numberOfExecutors(); uint256 currentSlotLength = slotLength(); require( numberOfExecutors > 0, "LibConcurrentCanExec.getCurrentExecutorIndex: 0 executors" ); require( currentSlotLength > 0, "LibConcurrentCanExec.getCurrentExecutorIndex: 0 slotLength" ); return calcExecutorIndex( _currentBlock, currentSlotLength, numberOfExecutors ); } function currentExecutor() internal view returns ( address executor, uint256 executorIndex, uint256 remainingBlocksInSlot ) { (executorIndex, remainingBlocksInSlot) = getCurrentExecutorIndexAtBlock( block.number ); executor = LibExecutor.executorAt(executorIndex); } function mySlotStatus(uint256 _buffer) internal view returns (SlotStatus) { require( _buffer < slotLength(), "LibConcurrentCanExec.mySlotStatus: invalid _buffer" ); ( uint256 executorIndex, uint256 remainingBlocksInSlot ) = getCurrentExecutorIndexAtBlock(block.number); address executor = LibExecutor.executorAt(executorIndex); // The next executor should be able to exec if the previous executor's // slot has 0 remaining blocks if (msg.sender != executor) { if (remainingBlocksInSlot == 0) { (uint256 nextExecutorIndex, ) = getCurrentExecutorIndexAtBlock( block.number + 1 ); address nextExecutor = LibExecutor.executorAt( nextExecutorIndex ); if (msg.sender == nextExecutor) return SlotStatus.Open; return SlotStatus.Closed; // msg.sender not nextExecutor } // Current Executor has remaining blocks in slot return SlotStatus.Closed; } return remainingBlocksInSlot <= _buffer ? SlotStatus.Closing : SlotStatus.Open; } // Example: blocksPerSlot = 3, numberOfExecutors = 2 // // Block number 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... // --------------------------------------------- // slotIndex 0 | 0 | 0 | 1 | 1 | 1 | 2 | 2 | 2 | 3 | ... // --------------------------------------------- // executorIndex 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | ... // remainingBlocksInSlot 2 | 1 | 0 | 2 | 1 | 0 | 2 | 1 | 0 | 2 | ... // function calcExecutorIndex( uint256 _currentBlock, uint256 _blocksPerSlot, uint256 _numberOfExecutors ) internal pure returns (uint256 executorIndex, uint256 remainingBlocksInSlot) { uint256 slotIndex = _currentBlock / _blocksPerSlot; return ( slotIndex % _numberOfExecutors, (slotIndex + 1) * _blocksPerSlot - _currentBlock - 1 ); } function concurrentExecStorage() internal pure returns (ConcurrentExecStorage storage ces) { bytes32 position = _CONCURRENT_EXEC_STORAGE_POSITION; assembly { ces.slot := position } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; library LibExecutor { using EnumerableSet for EnumerableSet.AddressSet; struct ExecutorStorage { EnumerableSet.AddressSet executors; uint256 gasMargin; EnumerableSet.AddressSet bundleExecutors; } bytes32 private constant _EXECUTOR_STORAGE_POSITION = keccak256("gelato.diamond.executor.storage"); function addExecutor(address _executor) internal returns (bool) { return executorStorage().executors.add(_executor); } function addBundleExecutor(address _bundleExecutor) internal returns (bool) { return executorStorage().bundleExecutors.add(_bundleExecutor); } function removeExecutor(address _executor) internal returns (bool) { return executorStorage().executors.remove(_executor); } function removeBundleExecutor(address _bundleExecutor) internal returns (bool) { return executorStorage().bundleExecutors.remove(_bundleExecutor); } function setGasMargin(uint256 _gasMargin) internal { executorStorage().gasMargin = _gasMargin; } function canExec(address _executor) internal view returns (bool) { return isExecutor(_executor); } function isExecutor(address _executor) internal view returns (bool) { return executorStorage().executors.contains(_executor); } function isBundleExecutor(address _bundleExecutor) internal view returns (bool) { return executorStorage().bundleExecutors.contains(_bundleExecutor); } function executorAt(uint256 _index) internal view returns (address) { return executorStorage().executors.at(_index); } function bundleExecutorAt(uint256 _index) internal view returns (address) { return executorStorage().bundleExecutors.at(_index); } function executors() internal view returns (address[] memory executors_) { uint256 length = numberOfExecutors(); executors_ = new address[](length); for (uint256 i; i < length; i++) executors_[i] = executorAt(i); } function bundleExecutors() internal view returns (address[] memory bundleExecutors_) { uint256 length = numberOfBundleExecutors(); bundleExecutors_ = new address[](length); for (uint256 i; i < length; i++) bundleExecutors_[i] = bundleExecutorAt(i); } function numberOfExecutors() internal view returns (uint256) { return executorStorage().executors.length(); } function numberOfBundleExecutors() internal view returns (uint256) { return executorStorage().bundleExecutors.length(); } function gasMargin() internal view returns (uint256) { return executorStorage().gasMargin; } function executorStorage() internal pure returns (ExecutorStorage storage es) { bytes32 position = _EXECUTOR_STORAGE_POSITION; assembly { es.slot := position } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; // solhint-disable max-line-length // https://github.com/mudgen/diamond-3/blob/b009cd08b7822bad727bbcc47aa1b50d8b50f7f0/contracts/libraries/LibDiamond.sol#L1 /******************************************************************************\ * Author: Nick Mudge <[email protected]> (https://twitter.com/mudgen) * EIP-2535 Diamond Standard: https://eips.ethereum.org/EIPS/eip-2535 /******************************************************************************/ import "../../interfaces/standard/IDiamondCut.sol"; // Custom due to incorrect string casting (non UTF-8 formatted) import {GelatoBytes} from "../../../lib/GelatoBytes.sol"; library LibDiamond { bytes32 constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage"); struct FacetAddressAndPosition { address facetAddress; uint16 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array } struct FacetFunctionSelectors { bytes4[] functionSelectors; uint16 facetAddressPosition; // position of facetAddress in facetAddresses array } struct DiamondStorage { // maps function selector to the facet address and // the position of the selector in the facetFunctionSelectors.selectors array mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition; // maps facet addresses to function selectors mapping(address => FacetFunctionSelectors) facetFunctionSelectors; // facet addresses address[] facetAddresses; // Used to query if a contract implements an interface. // Used to implement ERC-165. mapping(bytes4 => bool) supportedInterfaces; // owner of the contract address contractOwner; } function diamondStorage() internal pure returns (DiamondStorage storage ds) { bytes32 position = DIAMOND_STORAGE_POSITION; assembly { ds.slot := position } } event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); function setContractOwner(address _newOwner) internal { DiamondStorage storage ds = diamondStorage(); address previousOwner = ds.contractOwner; ds.contractOwner = _newOwner; emit OwnershipTransferred(previousOwner, _newOwner); } function contractOwner() internal view returns (address contractOwner_) { contractOwner_ = diamondStorage().contractOwner; } function isContractOwner(address _guy) internal view returns (bool) { return _guy == contractOwner(); } function enforceIsContractOwner() internal view { require( msg.sender == diamondStorage().contractOwner, "LibDiamond: Must be contract owner" ); } event DiamondCut( IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata ); // Internal function version of diamondCut function diamondCut( IDiamondCut.FacetCut[] memory _diamondCut, address _init, bytes memory _calldata ) internal { for ( uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++ ) { IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action; if (action == IDiamondCut.FacetCutAction.Add) { addFunctions( _diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors ); } else if (action == IDiamondCut.FacetCutAction.Replace) { replaceFunctions( _diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors ); } else if (action == IDiamondCut.FacetCutAction.Remove) { removeFunctions( _diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors ); } else { revert("LibDiamondCut: Incorrect FacetCutAction"); } } emit DiamondCut(_diamondCut, _init, _calldata); initializeDiamondCut(_init, _calldata); } function addFunctions( address _facetAddress, bytes4[] memory _functionSelectors ) internal { require( _functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut" ); DiamondStorage storage ds = diamondStorage(); // uint16 selectorCount = uint16(diamondStorage().selectors.length); require( _facetAddress != address(0), "LibDiamondCut: Add facet can't be address(0)" ); uint16 selectorPosition = uint16( ds.facetFunctionSelectors[_facetAddress].functionSelectors.length ); // add new facet address if it does not exist if (selectorPosition == 0) { enforceHasContractCode( _facetAddress, "LibDiamondCut: New facet has no code" ); ds .facetFunctionSelectors[_facetAddress] .facetAddressPosition = uint16(ds.facetAddresses.length); ds.facetAddresses.push(_facetAddress); } for ( uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++ ) { bytes4 selector = _functionSelectors[selectorIndex]; address oldFacetAddress = ds .selectorToFacetAndPosition[selector] .facetAddress; require( oldFacetAddress == address(0), "LibDiamondCut: Can't add function that already exists" ); ds.facetFunctionSelectors[_facetAddress].functionSelectors.push( selector ); ds .selectorToFacetAndPosition[selector] .facetAddress = _facetAddress; ds .selectorToFacetAndPosition[selector] .functionSelectorPosition = selectorPosition; selectorPosition++; } } function replaceFunctions( address _facetAddress, bytes4[] memory _functionSelectors ) internal { require( _functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut" ); DiamondStorage storage ds = diamondStorage(); require( _facetAddress != address(0), "LibDiamondCut: Add facet can't be address(0)" ); uint16 selectorPosition = uint16( ds.facetFunctionSelectors[_facetAddress].functionSelectors.length ); // add new facet address if it does not exist if (selectorPosition == 0) { enforceHasContractCode( _facetAddress, "LibDiamondCut: New facet has no code" ); ds .facetFunctionSelectors[_facetAddress] .facetAddressPosition = uint16(ds.facetAddresses.length); ds.facetAddresses.push(_facetAddress); } for ( uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++ ) { bytes4 selector = _functionSelectors[selectorIndex]; address oldFacetAddress = ds .selectorToFacetAndPosition[selector] .facetAddress; require( oldFacetAddress != _facetAddress, "LibDiamondCut: Can't replace function with same function" ); removeFunction(oldFacetAddress, selector); // add function ds .selectorToFacetAndPosition[selector] .functionSelectorPosition = selectorPosition; ds.facetFunctionSelectors[_facetAddress].functionSelectors.push( selector ); ds .selectorToFacetAndPosition[selector] .facetAddress = _facetAddress; selectorPosition++; } } function removeFunctions( address _facetAddress, bytes4[] memory _functionSelectors ) internal { require( _functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut" ); DiamondStorage storage ds = diamondStorage(); // if function does not exist then do nothing and return require( _facetAddress == address(0), "LibDiamondCut: Remove facet address must be address(0)" ); for ( uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++ ) { bytes4 selector = _functionSelectors[selectorIndex]; address oldFacetAddress = ds .selectorToFacetAndPosition[selector] .facetAddress; removeFunction(oldFacetAddress, selector); } } function removeFunction(address _facetAddress, bytes4 _selector) internal { DiamondStorage storage ds = diamondStorage(); require( _facetAddress != address(0), "LibDiamondCut: Can't remove function that doesn't exist" ); // an immutable function is a function defined directly in a diamond require( _facetAddress != address(this), "LibDiamondCut: Can't remove immutable function" ); // replace selector with last selector, then delete last selector uint256 selectorPosition = ds .selectorToFacetAndPosition[_selector] .functionSelectorPosition; uint256 lastSelectorPosition = ds .facetFunctionSelectors[_facetAddress] .functionSelectors .length - 1; // if not the same then replace _selector with lastSelector if (selectorPosition != lastSelectorPosition) { bytes4 lastSelector = ds .facetFunctionSelectors[_facetAddress] .functionSelectors[lastSelectorPosition]; ds.facetFunctionSelectors[_facetAddress].functionSelectors[ selectorPosition ] = lastSelector; ds .selectorToFacetAndPosition[lastSelector] .functionSelectorPosition = uint16(selectorPosition); } // delete the last selector ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop(); delete ds.selectorToFacetAndPosition[_selector]; // if no more selectors for facet address then delete the facet address if (lastSelectorPosition == 0) { // replace facet address with last facet address and delete last facet address uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1; uint256 facetAddressPosition = ds .facetFunctionSelectors[_facetAddress] .facetAddressPosition; if (facetAddressPosition != lastFacetAddressPosition) { address lastFacetAddress = ds.facetAddresses[ lastFacetAddressPosition ]; ds.facetAddresses[facetAddressPosition] = lastFacetAddress; ds .facetFunctionSelectors[lastFacetAddress] .facetAddressPosition = uint16(facetAddressPosition); } ds.facetAddresses.pop(); delete ds .facetFunctionSelectors[_facetAddress] .facetAddressPosition; } } function initializeDiamondCut(address _init, bytes memory _calldata) internal { if (_init == address(0)) { require( _calldata.length == 0, "LibDiamondCut: _init is address(0) but_calldata is not empty" ); } else { require( _calldata.length > 0, "LibDiamondCut: _calldata is empty but _init is not address(0)" ); if (_init != address(this)) { enforceHasContractCode( _init, "LibDiamondCut: _init address has no code" ); } (bool success, bytes memory error) = _init.delegatecall(_calldata); if (!success) { if (error.length > 0) { // bubble up the error GelatoBytes.revertWithError(error, "LibDiamondCut:_init:"); } else { revert("LibDiamondCut: _init function reverted"); } } } } function enforceHasContractCode( address _contract, string memory _errorMessage ) internal view { uint256 contractSize; assembly { contractSize := extcodesize(_contract) } require(contractSize > 0, _errorMessage); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; library GelatoBytes { function calldataSliceSelector(bytes calldata _bytes) internal pure returns (bytes4 selector) { selector = _bytes[0] | (bytes4(_bytes[1]) >> 8) | (bytes4(_bytes[2]) >> 16) | (bytes4(_bytes[3]) >> 24); } function memorySliceSelector(bytes memory _bytes) internal pure returns (bytes4 selector) { selector = _bytes[0] | (bytes4(_bytes[1]) >> 8) | (bytes4(_bytes[2]) >> 16) | (bytes4(_bytes[3]) >> 24); } function revertWithError(bytes memory _bytes, string memory _tracingInfo) internal pure { // 68: 32-location, 32-length, 4-ErrorSelector, UTF-8 err if (_bytes.length % 32 == 4) { bytes4 selector; assembly { selector := mload(add(0x20, _bytes)) } if (selector == 0x08c379a0) { // Function selector for Error(string) assembly { _bytes := add(_bytes, 68) } revert(string(abi.encodePacked(_tracingInfo, string(_bytes)))); } else { revert( string(abi.encodePacked(_tracingInfo, "NoErrorSelector")) ); } } else { revert( string(abi.encodePacked(_tracingInfo, "UnexpectedReturndata")) ); } } function returnError(bytes memory _bytes, string memory _tracingInfo) internal pure returns (string memory) { // 68: 32-location, 32-length, 4-ErrorSelector, UTF-8 err if (_bytes.length % 32 == 4) { bytes4 selector; assembly { selector := mload(add(0x20, _bytes)) } if (selector == 0x08c379a0) { // Function selector for Error(string) assembly { _bytes := add(_bytes, 68) } return string(abi.encodePacked(_tracingInfo, string(_bytes))); } else { return string(abi.encodePacked(_tracingInfo, "NoErrorSelector")); } } else { return string(abi.encodePacked(_tracingInfo, "UnexpectedReturndata")); } } }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"_currentBlock","type":"uint256"},{"internalType":"uint256","name":"_blocksPerSlot","type":"uint256"},{"internalType":"uint256","name":"_numberOfExecutors","type":"uint256"}],"name":"calcExecutorIndex","outputs":[{"internalType":"uint256","name":"executorIndex","type":"uint256"},{"internalType":"uint256","name":"remainingBlocksInSlot","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_buffer","type":"uint256"}],"name":"concurrentCanExec","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentExecutor","outputs":[{"internalType":"address","name":"executor","type":"address"},{"internalType":"uint256","name":"executorIndex","type":"uint256"},{"internalType":"uint256","name":"remainingBlocksInSlot","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentExecutorIndex","outputs":[{"internalType":"uint256","name":"executorIndex","type":"uint256"},{"internalType":"uint256","name":"remainingBlocksInSlot","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_buffer","type":"uint256"}],"name":"mySlotStatus","outputs":[{"internalType":"enum LibConcurrentCanExec.SlotStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_slotLength","type":"uint256"}],"name":"setSlotLength","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slotLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50610822806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80636b60a09b1161005b5780636b60a09b146100f6578063878e19f214610123578063c81ff7b61461012b578063d838b5de1461014157600080fd5b80630976635e146100825780633da31560146100ab5780635d801a03146100ce575b600080fd5b610095610090366004610691565b610156565b6040516100a291906106c0565b60405180910390f35b6100be6100b9366004610691565b610167565b60405190151581526020016100a2565b6100e16100dc3660046106e8565b610172565b604080519283526020830191909152016100a2565b6100fe61018c565b604080516001600160a01b0390941684526020840192909252908201526060016100a2565b6100e16101a4565b6101336101b8565b6040519081526020016100a2565b61015461014f366004610691565b6101d5565b005b6000610161826101f6565b92915050565b600061016182610324565b600080610180858585610370565b91509150935093915050565b60008060006101996103c3565b925092509250909192565b6000806101b0436103e6565b915091509091565b60006101d06000805160206107cd8339815191525490565b905090565b6101dd610511565b6101f3816000805160206107cd83398151915255565b50565b600061020e6000805160206107cd8339815191525490565b821061027c5760405162461bcd60e51b815260206004820152603260248201527f4c6962436f6e63757272656e7443616e457865632e6d79536c6f745374617475604482015271399d1034b73b30b634b2102fb13ab33332b960711b60648201526084015b60405180910390fd5b600080610288436103e6565b9150915060006102978361059a565b9050336001600160a01b0382161461030957816102fe5760006102c36102be43600161072a565b6103e6565b50905060006102d18261059a565b9050336001600160a01b03821614156102f1575060009695505050505050565b5060029695505050505050565b506002949350505050565b8482111561031857600061031b565b60015b95945050505050565b600061032f336105c6565b8015610342575061033e6105d1565b6001145b610368576000610351836101f6565b6002811115610362576103626106aa565b14610161565b600192915050565b6000808061037e8587610758565b905061038a848261076c565b60018787610398858461072a565b6103a29190610780565b6103ac919061079f565b6103b6919061079f565b9250925050935093915050565b60008060006103d1436103e6565b90925090506103df8261059a565b9250909192565b60008060006103f36105d1565b9050600061040d6000805160206107cd8339815191525490565b9050600082116104855760405162461bcd60e51b815260206004820152603960248201527f4c6962436f6e63757272656e7443616e457865632e67657443757272656e744560448201527f78656375746f72496e6465783a2030206578656375746f7273000000000000006064820152608401610273565b600081116104fb5760405162461bcd60e51b815260206004820152603a60248201527f4c6962436f6e63757272656e7443616e457865632e67657443757272656e744560448201527f78656375746f72496e6465783a203020736c6f744c656e6774680000000000006064820152608401610273565b610506858284610370565b935093505050915091565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c600401546001600160a01b031633146105985760405162461bcd60e51b815260206004820152602260248201527f4c69624469616d6f6e643a204d75737420626520636f6e7472616374206f776e60448201526132b960f11b6064820152608401610273565b565b60006101617f7ad725e6d99a082d357ed78c93550a4ac89ca228cbbe8e92f3140a9c2a3effa5836105fc565b60006101618261060f565b60006101d07f7ad725e6d99a082d357ed78c93550a4ac89ca228cbbe8e92f3140a9c2a3effa561063b565b60006106088383610645565b9392505050565b60006101617f7ad725e6d99a082d357ed78c93550a4ac89ca228cbbe8e92f3140a9c2a3effa58361066f565b6000610161825490565b600082600001828154811061065c5761065c6107b6565b9060005260206000200154905092915050565b6001600160a01b03811660009081526001830160205260408120541515610608565b6000602082840312156106a357600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60208101600383106106e257634e487b7160e01b600052602160045260246000fd5b91905290565b6000806000606084860312156106fd57600080fd5b505081359360208301359350604090920135919050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561073d5761073d610714565b500190565b634e487b7160e01b600052601260045260246000fd5b60008261076757610767610742565b500490565b60008261077b5761077b610742565b500690565b600081600019048311821515161561079a5761079a610714565b500290565b6000828210156107b1576107b1610714565b500390565b634e487b7160e01b600052603260045260246000fdfec91339060d88da02fa85fa2f25e8f10498ff5141018c9ced5551e81fbd323cbfa26469706673582212206c2f49fd70411bfecadac97442683fb181bd34c457bb39305ff21933f538950e64736f6c634300080a0033
Loading...
Loading
Loading...
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.
[ 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.