From f88b75a860174780336d695672123ae82489c75c Mon Sep 17 00:00:00 2001 From: linguopeng Date: Thu, 21 Jul 2022 14:17:03 +0800 Subject: [PATCH 1/7] test: add filter,issue301 test --- contracts/contracts/issue301.sol | 787 ++++++++++++++++++++++++++++ contracts/contracts/logContract.sol | 61 +++ contracts/test/issue.js | 284 ++++++++++ 3 files changed, 1132 insertions(+) create mode 100644 contracts/contracts/issue301.sol create mode 100644 contracts/contracts/logContract.sol create mode 100644 contracts/test/issue.js diff --git a/contracts/contracts/issue301.sol b/contracts/contracts/issue301.sol new file mode 100644 index 00000000..fad786a1 --- /dev/null +++ b/contracts/contracts/issue301.sol @@ -0,0 +1,787 @@ +// 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); + } + } + } +} + + +abstract contract Initializable { + /** + * @dev Indicates that the contract has been initialized. + * @custom:oz-retyped-from bool + */ + uint8 private _initialized; + + /** + * @dev Indicates that the contract is in the process of being initialized. + */ + bool private _initializing; + + /** + * @dev Triggered when the contract has been initialized or reinitialized. + */ + event Initialized(uint8 version); + + /** + * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, + * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. + */ + modifier initializer() { + bool isTopLevelCall = _setInitializedVersion(1); + if (isTopLevelCall) { + _initializing = true; + } + _; + if (isTopLevelCall) { + _initializing = false; + emit Initialized(1); + } + } + + /** + * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the + * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be + * used to initialize parent contracts. + * + * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original + * initialization step. This is essential to configure modules that are added through upgrades and that require + * initialization. + * + * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in + * a contract, executing them in the right order is up to the developer or operator. + */ + modifier reinitializer(uint8 version) { + bool isTopLevelCall = _setInitializedVersion(version); + if (isTopLevelCall) { + _initializing = true; + } + _; + if (isTopLevelCall) { + _initializing = false; + emit Initialized(version); + } + } + + /** + * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the + * {initializer} and {reinitializer} modifiers, directly or indirectly. + */ + modifier onlyInitializing() { + require(_initializing, "Initializable: contract is not initializing"); + _; + } + + /** + * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. + * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized + * to any version. It is recommended to use this to lock implementation contracts that are designed to be called + * through proxies. + */ + function _disableInitializers() internal virtual { + _setInitializedVersion(type(uint8).max); + } + + 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 (_initializing) { + require( + version == 1 && !Address.isContract(address(this)), + "Initializable: contract is already initialized" + ); + return false; + } else { + require(_initialized < version, "Initializable: contract is already initialized"); + _initialized = version; + return true; + } + } +} + +contract Implementation2 is Initializable { + uint256 internal _value; + + function initialize() public initializer {} + + function setValue(uint256 _number) public { + _value = _number; + } + + function getValue() public view returns (uint256) { + return _value; + } +} +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 + } + } +} + +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); +} + +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); +} + + +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); + } + } +} + +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 {} +} + +contract ERC1967Proxy is Proxy, ERC1967Upgrade { + /** + * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`. + * + * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded + * function call, and allows initializating the storage of the proxy like a Solidity constructor. + */ + constructor(address _logic, bytes memory _data) payable { + assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)); + _upgradeToAndCall(_logic, _data, false); + } + + /** + * @dev Returns the current implementation address. + */ + function _implementation() internal view virtual override returns (address impl) { + return ERC1967Upgrade._getImplementation(); + } +} + +contract TransparentUpgradeableProxy is ERC1967Proxy { + /** + * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and + * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}. + */ + constructor( + address _logic, + address admin_, + bytes memory _data + ) payable ERC1967Proxy(_logic, _data) { + assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)); + _changeAdmin(admin_); + } + + /** + * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. + */ + modifier ifAdmin() { + if (msg.sender == _getAdmin()) { + _; + } else { + _fallback(); + } + } + + /** + * @dev Returns the current admin. + * + * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. + * + * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the + * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. + * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` + */ + function admin() external ifAdmin returns (address admin_) { + admin_ = _getAdmin(); + } + + /** + * @dev Returns the current implementation. + * + * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. + * + * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the + * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. + * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` + */ + function implementation() external ifAdmin returns (address implementation_) { + implementation_ = _implementation(); + } + + /** + * @dev Changes the admin of the proxy. + * + * Emits an {AdminChanged} event. + * + * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}. + */ + function changeAdmin(address newAdmin) external virtual ifAdmin { + _changeAdmin(newAdmin); + } + + /** + * @dev Upgrade the implementation of the proxy. + * + * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}. + */ + function upgradeTo(address newImplementation) external ifAdmin { + _upgradeToAndCall(newImplementation, bytes(""), false); + } + + /** + * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified + * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the + * proxied contract. + * + * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}. + */ + function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin { + _upgradeToAndCall(newImplementation, data, true); + } + + /** + * @dev Returns the current admin. + */ + function _admin() internal view virtual returns (address) { + return _getAdmin(); + } + + /** + * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}. + */ + function _beforeFallback() internal virtual override { + require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target"); + super._beforeFallback(); + } +} + +contract issue301{ + + // Implementation2 impl; + TransparentUpgradeableProxy public proxy; + + function TestProxy() public { + Implementation2 impl = new Implementation2(); + proxy = new TransparentUpgradeableProxy(address(impl),0x56109495D7A3D94F5e7b80280679b339E87BC237,""); + Implementation2 impl2 = Implementation2(address(proxy)); + impl2.setValue(42); + uint256 value = impl2.getValue(); + require(value == 42,"must eq 42"); + } + + function setAndGet(uint256 num) public { + Implementation2 impl2 = Implementation2(address(proxy)); + impl2.setValue(num); + uint256 value = impl2.getValue(); + require(value == num,"must eq num"); + } + +} diff --git a/contracts/contracts/logContract.sol b/contracts/contracts/logContract.sol new file mode 100644 index 00000000..5d42cbf7 --- /dev/null +++ b/contracts/contracts/logContract.sol @@ -0,0 +1,61 @@ +pragma solidity >=0.4.21 <0.6.0; + +contract logContract { + + constructor() public payable{ + log1234(); + } + function log1234() public { + //log0 + uint256 _id = 0x420042; + + log0( + bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20) + ); + + //log1 + log1( + bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20), + bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20) + ); + + //log2 + log2( + bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20), + bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20), + bytes32(uint256(msg.sender)) + ); + + //log3 + log3( + bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20), + bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20), + bytes32(uint256(msg.sender)), + bytes32(_id) + ); + + //log4 + log4( + bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20), + bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20), + bytes32(uint256(msg.sender)), + bytes32(_id), + bytes32(_id) + + ); + + } + + function testLog4(uint256 logCount) public { + for(uint256 i=0;i { + const filterId = await ethers.provider.send("eth_newFilter", [{}]); + + await sendTxToAddBlockNum(3) + let logs = await ethers.provider.send("eth_getFilterChanges", [filterId]); + checkLogsIsSort(logs) + logs = await ethers.provider.send("eth_getFilterChanges", [filterId]); + expect(logs.toString()).to.be.equal('') + }) + + describe('filter', function () { + + let blockHeight + let filterMsg; + before(async function () { + blockHeight = await ethers.provider.getBlockNumber() + + filterMsg = await getFilterMsgByFilter( + { + + "fromBlock.pending": { + 'fromBlock': 'pending' + }, + "fromBlock.blockHeight+1000": { + 'fromBlock': BigNumber.from(blockHeight).add(1000).toHexString().replace('0x0', '0x') + }, + + "toBlock.earliest": { + "toBlock": "earliest" + }, + }, 3) + }); + + + describe("fromBlock", function () { + + + it.skip("pending,should return error msg", async () => { + //invalid from and to block combination: from > to + expect(filterMsg["fromBlock.pending"].error).to.be.not.equal(undefined) + + }) + + + it.skip("blockNumber(blockHeight+1000),should return 0 log", async () => { + + expect(filterMsg["fromBlock.blockHeight+1000"].logs.length).to.be.equal(0) + }) + + }) + + describe('toBlock', function () { + + it.skip("earliest,should return error msg", async () => { + //invalid from and to block combination: from > to + expect(filterMsg["toBlock.earliest"].error).to.be.not.equal(undefined) + }) + + }); + + describe('topic', function () { + + let contractAddress; + + let topic0 = "0x0000000000000000000000000000000000000000000000000000000000000001"; + let topic1 = "0x0000000000000000000000000000000000000000000000000000000000000002"; + let topic2 = "0x0000000000000000000000000000000000000000000000000000000000000003"; + let topic3 = "0x0000000000000000000000000000000000000000000000000000000000000004"; + let filterMsgMap; + let logContract; + let blockHeight; + + before(async function () { + + blockHeight = await ethers.provider.getBlockNumber() + //deploy contract + let logContractInfo = await ethers.getContractFactory("logContract"); + logContract = await logContractInfo.deploy() + await logContract.deployed() + contractAddress = logContract.address + let topicsMap = { + + "topic.[[A, B],[A, B]].yes": { + "topics": [[topic3, topic0], [null, null, topic2]] + }, + "topic.[[A, B],[A, B]].no": { + "topics": [[topic0, topic2, topic3], [null, topic2], [topic1]] + }, + } + + filterMsgMap = await getTopicFilter(topicsMap, logContract, 10) + }) + + it.skip("[[A, B], [A, B]].yes", async () => { + //check get filed id success + expect(filterMsgMap["topic.[[A, B],[A, B]].yes"].error).to.be.equal(undefined) + expect(filterMsgMap["topic.[[A, B],[A, B]].yes"].logs.length).to.be.not.equal(0) + await checkLogsGteHeight(filterMsgMap["topic.[[A, B],[A, B]].yes"].logs, blockHeight) + await checkLogsIsSort(filterMsgMap["topic.[[A, B],[A, B]].yes"].logs) + }) + + it.skip("[[A, B], [A, B]].no", async () => { + expect(filterMsgMap["topic.[[A, B],[A, B]].no"].error).to.be.equal(undefined) + expect(filterMsgMap["topic.[[A, B],[A, B]].no"].logs.length).to.be.equal(0) + }) + + }); + + + }); + + }); + + +}); + + +/** + * 1. filter + * 2. send tx + * 3. get filter change log msg + * @param topicFilterMap + * @param logContract + * @param sendCount + * @returns filterMsgMap: filter change log msg + */ +async function getTopicFilter(topicFilterMap, logContract, sendCount) { + + let filterMsgMap = {} + + // register filter Id + for (const key in topicFilterMap) { + filterMsgMap[key] = {} + try { + filterMsgMap[key].filterId = await ethers.provider.send("eth_newFilter", [topicFilterMap[key]]) + } catch (e) { + filterMsgMap[key].error = e + } + } + + // invoke contract + let nonce = await ethers.provider.getTransactionCount(logContract.signer.address, "latest") + let txList = [] + for (let i = 0; i < sendCount; i++) { + let tx = await logContract.testLog4(500, {nonce: nonce}) + await sleep(500) + nonce++ + txList.push(tx) + } + + for (let i = 0; i < txList.length; i++) { + await txList[i].wait(1) + } + + // get filter result + + for (const key in filterMsgMap) { + if (filterMsgMap[key].filterId === undefined) { + continue + } + try { + filterMsgMap[key].logs = await ethers.provider.send("eth_getFilterChanges", [filterMsgMap[key].filterId]) + } catch (e) { + filterMsgMap[key].error = e + } + } + + return filterMsgMap + +} + +/** + * 1. filter + * 2. send tx + * 3. get filter change log + * @param filterMap + * @param sendBlkNum + * @returns FilterMsg: filter change log + */ +async function getFilterMsgByFilter(filterMap, sendBlkNum) { + let FilterMsg = {} + for (let key in filterMap) { + FilterMsg[key] = {} + try { + FilterMsg[key].filterMap = filterMap + FilterMsg[key].filterId = await ethers.provider.send("eth_newFilter", [filterMap[key]]) + } catch (e) { + FilterMsg[key].error = e + } + } + await sendTxToAddBlockNum(sendBlkNum) + for (let key in FilterMsg) { + try { + if (FilterMsg[key].filterId === undefined) { + continue + } + FilterMsg[key].logs = await ethers.provider.send("eth_getFilterChanges", [FilterMsg[key].filterId]) + } catch (e) { + FilterMsg[key].error = e + } + } + return FilterMsg +} + + +/** + * add block height use send tx + * @param blockNumber add block length + * @returns {Promise} + */ +async function sendTxToAddBlockNum(blockNumber) { + let endNumber = await ethers.provider.getBlockNumber() + blockNumber; + let currentNumber = await ethers.provider.getBlockNumber(); + while (currentNumber < endNumber) { + await sendTxContainsLog() + currentNumber = await ethers.provider.getBlockNumber(); + } +} + +/** + * use the second account send tx + * @returns {Promise} + */ +async function sendTxContainsLog() { + let from = (await ethers.getSigners())[1].address + let logContract = await ethers.getContractFactory("logContract"); + try { + await ethers.provider.send("eth_sendTransaction", [{ + "from": from, + "data": logContract.bytecode + }]); + } catch (e) { + } +} + +/** + * check log is sort + * @param logs + */ +function checkLogsIsSort(logs) { + let latestLog = "0x0"; + for (let i = 0; i < logs.length; i++) { + let currentSore = getScoreByLog(logs[i]) + // console.log("blockNumber:", BigNumber.from(logs[i].blockNumber.toString()).toString(), "blkIdx:", logs[i].transactionIndex, "logIndex:", logs[i].logIndex," score:",currentSore) + expect(currentSore).to.be.gt(latestLog) + latestLog = currentSore + } +} + +async function checkLogsGteHeight(logs, blockHeight) { + for (const log of logs) { + expect(BigNumber.from(log.blockNumber)).to.be.gte(blockHeight) + } +} + +/** + * get score by log + * @param log tx log + * @returns score (blockNum) * base**2 + (transactionIndex) * base + logIndex + */ +function getScoreByLog(log) { + const base = 100000; + let nowBlkNum = BigNumber.from(log.blockNumber); + let nowBlkIdx = BigNumber.from(log.transactionIndex); + let nowLogIdx = BigNumber.from(log.logIndex); + return nowBlkNum.mul(base * base).add(nowBlkIdx.mul(base)).add(nowLogIdx) +} + + +async function sleep(ms) { + return new Promise((resolve) => { + setTimeout(resolve, ms) + }) +} From 1999b30e08ad37991c17b79088ccd5dd738a91d5 Mon Sep 17 00:00:00 2001 From: linguopeng Date: Thu, 21 Jul 2022 14:48:56 +0800 Subject: [PATCH 2/7] fix: compile logContract.sol contract failed --- contracts/hardhat.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/hardhat.config.js b/contracts/hardhat.config.js index c3aaab6c..04113645 100644 --- a/contracts/hardhat.config.js +++ b/contracts/hardhat.config.js @@ -64,6 +64,7 @@ module.exports = { }, solidity: { compilers: [ + {version: "0.5.14"}, { // for polyjuice contracts version: "0.6.6", settings: {} From 105315aa47a35f4920b824c309aebf3774fe2c5c Mon Sep 17 00:00:00 2001 From: linguopeng Date: Thu, 21 Jul 2022 14:49:46 +0800 Subject: [PATCH 3/7] style: add test describe --- contracts/test/issue.js | 86 ++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/contracts/test/issue.js b/contracts/test/issue.js index 570e36c2..c77ae555 100644 --- a/contracts/test/issue.js +++ b/contracts/test/issue.js @@ -68,54 +68,54 @@ describe('issue', function () { }); - describe('topic', function () { - - let contractAddress; - - let topic0 = "0x0000000000000000000000000000000000000000000000000000000000000001"; - let topic1 = "0x0000000000000000000000000000000000000000000000000000000000000002"; - let topic2 = "0x0000000000000000000000000000000000000000000000000000000000000003"; - let topic3 = "0x0000000000000000000000000000000000000000000000000000000000000004"; - let filterMsgMap; - let logContract; - let blockHeight; - - before(async function () { - - blockHeight = await ethers.provider.getBlockNumber() - //deploy contract - let logContractInfo = await ethers.getContractFactory("logContract"); - logContract = await logContractInfo.deploy() - await logContract.deployed() - contractAddress = logContract.address - let topicsMap = { - - "topic.[[A, B],[A, B]].yes": { - "topics": [[topic3, topic0], [null, null, topic2]] - }, - "topic.[[A, B],[A, B]].no": { - "topics": [[topic0, topic2, topic3], [null, topic2], [topic1]] - }, - } - filterMsgMap = await getTopicFilter(topicsMap, logContract, 10) - }) + }); - it.skip("[[A, B], [A, B]].yes", async () => { - //check get filed id success - expect(filterMsgMap["topic.[[A, B],[A, B]].yes"].error).to.be.equal(undefined) - expect(filterMsgMap["topic.[[A, B],[A, B]].yes"].logs.length).to.be.not.equal(0) - await checkLogsGteHeight(filterMsgMap["topic.[[A, B],[A, B]].yes"].logs, blockHeight) - await checkLogsIsSort(filterMsgMap["topic.[[A, B],[A, B]].yes"].logs) - }) + describe('filter topic', function () { - it.skip("[[A, B], [A, B]].no", async () => { - expect(filterMsgMap["topic.[[A, B],[A, B]].no"].error).to.be.equal(undefined) - expect(filterMsgMap["topic.[[A, B],[A, B]].no"].logs.length).to.be.equal(0) - }) + let contractAddress; - }); + let topic0 = "0x0000000000000000000000000000000000000000000000000000000000000001"; + let topic1 = "0x0000000000000000000000000000000000000000000000000000000000000002"; + let topic2 = "0x0000000000000000000000000000000000000000000000000000000000000003"; + let topic3 = "0x0000000000000000000000000000000000000000000000000000000000000004"; + let filterMsgMap; + let logContract; + let blockHeight; + before(async function () { + + blockHeight = await ethers.provider.getBlockNumber() + //deploy contract + let logContractInfo = await ethers.getContractFactory("logContract"); + logContract = await logContractInfo.deploy() + await logContract.deployed() + contractAddress = logContract.address + let topicsMap = { + + "topic.[[A, B],[A, B]].yes": { + "topics": [[topic3, topic0], [null, null, topic2]] + }, + "topic.[[A, B],[A, B]].no": { + "topics": [[topic0, topic2, topic3], [null, topic2], [topic1]] + }, + } + + filterMsgMap = await getTopicFilter(topicsMap, logContract, 10) + }) + + it.skip("[[A, B], [A, B]].yes,should return logs", async () => { + //check get filed id success + expect(filterMsgMap["topic.[[A, B],[A, B]].yes"].error).to.be.equal(undefined) + expect(filterMsgMap["topic.[[A, B],[A, B]].yes"].logs.length).to.be.not.equal(0) + await checkLogsGteHeight(filterMsgMap["topic.[[A, B],[A, B]].yes"].logs, blockHeight) + await checkLogsIsSort(filterMsgMap["topic.[[A, B],[A, B]].yes"].logs) + }) + + it.skip("[[A, B], [A, B]].no,should return empty", async () => { + expect(filterMsgMap["topic.[[A, B],[A, B]].no"].error).to.be.equal(undefined) + expect(filterMsgMap["topic.[[A, B],[A, B]].no"].logs.length).to.be.equal(0) + }) }); From d51b87e4aea81dad4d84eb2eb1463b5040814139 Mon Sep 17 00:00:00 2001 From: linguopeng Date: Fri, 22 Jul 2022 14:22:16 +0800 Subject: [PATCH 4/7] style: mod contract name style: remove contract 301 that not use --- .../{logContract.sol => LogContract.sol} | 2 +- contracts/contracts/issue301.sol | 787 ------------------ contracts/test/{issue.js => Issue.js} | 14 +- 3 files changed, 8 insertions(+), 795 deletions(-) rename contracts/contracts/{logContract.sol => LogContract.sol} (98%) delete mode 100644 contracts/contracts/issue301.sol rename contracts/test/{issue.js => Issue.js} (94%) diff --git a/contracts/contracts/logContract.sol b/contracts/contracts/LogContract.sol similarity index 98% rename from contracts/contracts/logContract.sol rename to contracts/contracts/LogContract.sol index 5d42cbf7..a598c81d 100644 --- a/contracts/contracts/logContract.sol +++ b/contracts/contracts/LogContract.sol @@ -1,6 +1,6 @@ pragma solidity >=0.4.21 <0.6.0; -contract logContract { +contract LogContract { constructor() public payable{ log1234(); diff --git a/contracts/contracts/issue301.sol b/contracts/contracts/issue301.sol deleted file mode 100644 index fad786a1..00000000 --- a/contracts/contracts/issue301.sol +++ /dev/null @@ -1,787 +0,0 @@ -// 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); - } - } - } -} - - -abstract contract Initializable { - /** - * @dev Indicates that the contract has been initialized. - * @custom:oz-retyped-from bool - */ - uint8 private _initialized; - - /** - * @dev Indicates that the contract is in the process of being initialized. - */ - bool private _initializing; - - /** - * @dev Triggered when the contract has been initialized or reinitialized. - */ - event Initialized(uint8 version); - - /** - * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, - * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. - */ - modifier initializer() { - bool isTopLevelCall = _setInitializedVersion(1); - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(1); - } - } - - /** - * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the - * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be - * used to initialize parent contracts. - * - * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original - * initialization step. This is essential to configure modules that are added through upgrades and that require - * initialization. - * - * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in - * a contract, executing them in the right order is up to the developer or operator. - */ - modifier reinitializer(uint8 version) { - bool isTopLevelCall = _setInitializedVersion(version); - if (isTopLevelCall) { - _initializing = true; - } - _; - if (isTopLevelCall) { - _initializing = false; - emit Initialized(version); - } - } - - /** - * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the - * {initializer} and {reinitializer} modifiers, directly or indirectly. - */ - modifier onlyInitializing() { - require(_initializing, "Initializable: contract is not initializing"); - _; - } - - /** - * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. - * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized - * to any version. It is recommended to use this to lock implementation contracts that are designed to be called - * through proxies. - */ - function _disableInitializers() internal virtual { - _setInitializedVersion(type(uint8).max); - } - - 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 (_initializing) { - require( - version == 1 && !Address.isContract(address(this)), - "Initializable: contract is already initialized" - ); - return false; - } else { - require(_initialized < version, "Initializable: contract is already initialized"); - _initialized = version; - return true; - } - } -} - -contract Implementation2 is Initializable { - uint256 internal _value; - - function initialize() public initializer {} - - function setValue(uint256 _number) public { - _value = _number; - } - - function getValue() public view returns (uint256) { - return _value; - } -} -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 - } - } -} - -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); -} - -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); -} - - -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); - } - } -} - -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 {} -} - -contract ERC1967Proxy is Proxy, ERC1967Upgrade { - /** - * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`. - * - * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded - * function call, and allows initializating the storage of the proxy like a Solidity constructor. - */ - constructor(address _logic, bytes memory _data) payable { - assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)); - _upgradeToAndCall(_logic, _data, false); - } - - /** - * @dev Returns the current implementation address. - */ - function _implementation() internal view virtual override returns (address impl) { - return ERC1967Upgrade._getImplementation(); - } -} - -contract TransparentUpgradeableProxy is ERC1967Proxy { - /** - * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and - * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}. - */ - constructor( - address _logic, - address admin_, - bytes memory _data - ) payable ERC1967Proxy(_logic, _data) { - assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)); - _changeAdmin(admin_); - } - - /** - * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. - */ - modifier ifAdmin() { - if (msg.sender == _getAdmin()) { - _; - } else { - _fallback(); - } - } - - /** - * @dev Returns the current admin. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. - * - * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the - * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. - * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` - */ - function admin() external ifAdmin returns (address admin_) { - admin_ = _getAdmin(); - } - - /** - * @dev Returns the current implementation. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. - * - * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the - * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. - * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` - */ - function implementation() external ifAdmin returns (address implementation_) { - implementation_ = _implementation(); - } - - /** - * @dev Changes the admin of the proxy. - * - * Emits an {AdminChanged} event. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}. - */ - function changeAdmin(address newAdmin) external virtual ifAdmin { - _changeAdmin(newAdmin); - } - - /** - * @dev Upgrade the implementation of the proxy. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}. - */ - function upgradeTo(address newImplementation) external ifAdmin { - _upgradeToAndCall(newImplementation, bytes(""), false); - } - - /** - * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified - * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the - * proxied contract. - * - * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}. - */ - function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin { - _upgradeToAndCall(newImplementation, data, true); - } - - /** - * @dev Returns the current admin. - */ - function _admin() internal view virtual returns (address) { - return _getAdmin(); - } - - /** - * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}. - */ - function _beforeFallback() internal virtual override { - require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target"); - super._beforeFallback(); - } -} - -contract issue301{ - - // Implementation2 impl; - TransparentUpgradeableProxy public proxy; - - function TestProxy() public { - Implementation2 impl = new Implementation2(); - proxy = new TransparentUpgradeableProxy(address(impl),0x56109495D7A3D94F5e7b80280679b339E87BC237,""); - Implementation2 impl2 = Implementation2(address(proxy)); - impl2.setValue(42); - uint256 value = impl2.getValue(); - require(value == 42,"must eq 42"); - } - - function setAndGet(uint256 num) public { - Implementation2 impl2 = Implementation2(address(proxy)); - impl2.setValue(num); - uint256 value = impl2.getValue(); - require(value == num,"must eq num"); - } - -} diff --git a/contracts/test/issue.js b/contracts/test/Issue.js similarity index 94% rename from contracts/test/issue.js rename to contracts/test/Issue.js index c77ae555..57596bdc 100644 --- a/contracts/test/issue.js +++ b/contracts/test/Issue.js @@ -4,11 +4,11 @@ const {BigNumber} = require("ethers"); describe('issue', function () { - // this.timeout(600000) + this.timeout(600000) describe('newFilter', function () { - it.skip("invoke eth_getFilterChanges 2 times, second logs length must be 0 ", async () => { + it("invoke eth_getFilterChanges 2 times, second logs length must be 0 ", async () => { const filterId = await ethers.provider.send("eth_newFilter", [{}]); await sendTxToAddBlockNum(3) @@ -45,14 +45,14 @@ describe('issue', function () { describe("fromBlock", function () { - it.skip("pending,should return error msg", async () => { + it("pending,should return error msg", async () => { //invalid from and to block combination: from > to expect(filterMsg["fromBlock.pending"].error).to.be.not.equal(undefined) }) - it.skip("blockNumber(blockHeight+1000),should return 0 log", async () => { + it("blockNumber(blockHeight+1000),should return 0 log", async () => { expect(filterMsg["fromBlock.blockHeight+1000"].logs.length).to.be.equal(0) }) @@ -87,7 +87,7 @@ describe('issue', function () { blockHeight = await ethers.provider.getBlockNumber() //deploy contract - let logContractInfo = await ethers.getContractFactory("logContract"); + let logContractInfo = await ethers.getContractFactory("LogContract"); logContract = await logContractInfo.deploy() await logContract.deployed() contractAddress = logContract.address @@ -104,7 +104,7 @@ describe('issue', function () { filterMsgMap = await getTopicFilter(topicsMap, logContract, 10) }) - it.skip("[[A, B], [A, B]].yes,should return logs", async () => { + it("[[A, B], [A, B]].yes,should return logs", async () => { //check get filed id success expect(filterMsgMap["topic.[[A, B],[A, B]].yes"].error).to.be.equal(undefined) expect(filterMsgMap["topic.[[A, B],[A, B]].yes"].logs.length).to.be.not.equal(0) @@ -112,7 +112,7 @@ describe('issue', function () { await checkLogsIsSort(filterMsgMap["topic.[[A, B],[A, B]].yes"].logs) }) - it.skip("[[A, B], [A, B]].no,should return empty", async () => { + it("[[A, B], [A, B]].no,should return empty", async () => { expect(filterMsgMap["topic.[[A, B],[A, B]].no"].error).to.be.equal(undefined) expect(filterMsgMap["topic.[[A, B],[A, B]].no"].logs.length).to.be.equal(0) }) From 887aadda51bc73edfccc2d1e94b16f41f8520c12 Mon Sep 17 00:00:00 2001 From: linguopeng Date: Fri, 22 Jul 2022 18:11:35 +0800 Subject: [PATCH 5/7] style: mod contract name style: remove contract 301 that not use test: skip when main net --- contracts/test/Issue.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/contracts/test/Issue.js b/contracts/test/Issue.js index 57596bdc..d5fd4a79 100644 --- a/contracts/test/Issue.js +++ b/contracts/test/Issue.js @@ -1,10 +1,14 @@ const {expect} = require("chai"); const {ethers} = require("hardhat"); const {BigNumber} = require("ethers"); +const { isGwMainnetV1 } = require('../utils/network'); describe('issue', function () { this.timeout(600000) + if (isGwMainnetV1()) { + return; + } describe('newFilter', function () { @@ -25,7 +29,7 @@ describe('issue', function () { before(async function () { blockHeight = await ethers.provider.getBlockNumber() - filterMsg = await getFilterMsgByFilter( + filterMsg = await getFilterMsgAfterSendTx( { "fromBlock.pending": { @@ -61,7 +65,7 @@ describe('issue', function () { describe('toBlock', function () { - it.skip("earliest,should return error msg", async () => { + it("earliest,should return error msg", async () => { //invalid from and to block combination: from > to expect(filterMsg["toBlock.earliest"].error).to.be.not.equal(undefined) }) @@ -101,7 +105,7 @@ describe('issue', function () { }, } - filterMsgMap = await getTopicFilter(topicsMap, logContract, 10) + filterMsgMap = await getTopicFilterAfterSendTx(topicsMap, logContract, 10) }) it("[[A, B], [A, B]].yes,should return logs", async () => { @@ -134,7 +138,7 @@ describe('issue', function () { * @param sendCount * @returns filterMsgMap: filter change log msg */ -async function getTopicFilter(topicFilterMap, logContract, sendCount) { +async function getTopicFilterAfterSendTx(topicFilterMap, logContract, sendCount) { let filterMsgMap = {} @@ -187,7 +191,7 @@ async function getTopicFilter(topicFilterMap, logContract, sendCount) { * @param sendBlkNum * @returns FilterMsg: filter change log */ -async function getFilterMsgByFilter(filterMap, sendBlkNum) { +async function getFilterMsgAfterSendTx(filterMap, sendBlkNum) { let FilterMsg = {} for (let key in filterMap) { FilterMsg[key] = {} @@ -233,7 +237,7 @@ async function sendTxToAddBlockNum(blockNumber) { */ async function sendTxContainsLog() { let from = (await ethers.getSigners())[1].address - let logContract = await ethers.getContractFactory("logContract"); + let logContract = await ethers.getContractFactory("LogContract"); try { await ethers.provider.send("eth_sendTransaction", [{ "from": from, From 73dfa15fe9446813699f829730aa6f2f4b3d3670 Mon Sep 17 00:00:00 2001 From: linguopeng Date: Fri, 22 Jul 2022 18:12:18 +0800 Subject: [PATCH 6/7] test: remove timeout --- contracts/test/Issue.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/test/Issue.js b/contracts/test/Issue.js index d5fd4a79..7faae219 100644 --- a/contracts/test/Issue.js +++ b/contracts/test/Issue.js @@ -5,7 +5,7 @@ const { isGwMainnetV1 } = require('../utils/network'); describe('issue', function () { - this.timeout(600000) + // this.timeout(600000) if (isGwMainnetV1()) { return; } From bb5ba8f83c0fac4ae5fb6ddcc1ae5719234770d6 Mon Sep 17 00:00:00 2001 From: linguopeng Date: Fri, 22 Jul 2022 18:13:44 +0800 Subject: [PATCH 7/7] test: add skip type --- contracts/test/Issue.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/test/Issue.js b/contracts/test/Issue.js index 7faae219..e3631be6 100644 --- a/contracts/test/Issue.js +++ b/contracts/test/Issue.js @@ -12,7 +12,7 @@ describe('issue', function () { describe('newFilter', function () { - it("invoke eth_getFilterChanges 2 times, second logs length must be 0 ", async () => { + it.skip("invoke eth_getFilterChanges 2 times, second logs length must be 0 ", async () => { const filterId = await ethers.provider.send("eth_newFilter", [{}]); await sendTxToAddBlockNum(3) @@ -49,14 +49,14 @@ describe('issue', function () { describe("fromBlock", function () { - it("pending,should return error msg", async () => { + it.skip("pending,should return error msg", async () => { //invalid from and to block combination: from > to expect(filterMsg["fromBlock.pending"].error).to.be.not.equal(undefined) }) - it("blockNumber(blockHeight+1000),should return 0 log", async () => { + it.skip("blockNumber(blockHeight+1000),should return 0 log", async () => { expect(filterMsg["fromBlock.blockHeight+1000"].logs.length).to.be.equal(0) }) @@ -65,7 +65,7 @@ describe('issue', function () { describe('toBlock', function () { - it("earliest,should return error msg", async () => { + it.skip("earliest,should return error msg", async () => { //invalid from and to block combination: from > to expect(filterMsg["toBlock.earliest"].error).to.be.not.equal(undefined) }) @@ -108,7 +108,7 @@ describe('issue', function () { filterMsgMap = await getTopicFilterAfterSendTx(topicsMap, logContract, 10) }) - it("[[A, B], [A, B]].yes,should return logs", async () => { + it.skip("[[A, B], [A, B]].yes,should return logs", async () => { //check get filed id success expect(filterMsgMap["topic.[[A, B],[A, B]].yes"].error).to.be.equal(undefined) expect(filterMsgMap["topic.[[A, B],[A, B]].yes"].logs.length).to.be.not.equal(0) @@ -116,7 +116,7 @@ describe('issue', function () { await checkLogsIsSort(filterMsgMap["topic.[[A, B],[A, B]].yes"].logs) }) - it("[[A, B], [A, B]].no,should return empty", async () => { + it.skip("[[A, B], [A, B]].no,should return empty", async () => { expect(filterMsgMap["topic.[[A, B],[A, B]].no"].error).to.be.equal(undefined) expect(filterMsgMap["topic.[[A, B],[A, B]].no"].logs.length).to.be.equal(0) })