Update docs
This commit is contained in:
@ -5,6 +5,8 @@ set -euo pipefail
|
||||
export COVERAGE=true
|
||||
export FOUNDRY_FUZZ_RUNS=10
|
||||
|
||||
. scripts/set-max-old-space-size.sh
|
||||
|
||||
# Hardhat coverage
|
||||
hardhat coverage
|
||||
|
||||
@ -12,7 +14,11 @@ if [ "${CI:-"false"}" == "true" ]; then
|
||||
# Foundry coverage
|
||||
forge coverage --report lcov --ir-minimum
|
||||
# Remove zero hits
|
||||
sed -i '/,0/d' lcov.info
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
sed -i '' '/,0/d' lcov.info
|
||||
else
|
||||
sed -i '/,0/d' lcov.info
|
||||
fi
|
||||
fi
|
||||
|
||||
# Reports are then uploaded to Codecov automatically by workflow, and merged.
|
||||
|
||||
@ -31,7 +31,7 @@ for (const artifact of artifacts) {
|
||||
}
|
||||
|
||||
/// graphlib.alg.findCycles will not find minimal cycles.
|
||||
/// We are only interested int cycles of lengths 2 (needs proof)
|
||||
/// We are only interested in cycles of lengths 2 (needs proof)
|
||||
graph.nodes().forEach((x, i, nodes) =>
|
||||
nodes
|
||||
.slice(i + 1)
|
||||
|
||||
@ -31,7 +31,7 @@ for (const artifact of artifacts) {
|
||||
const minVersion = semver.minVersion(pragma[source]);
|
||||
// loop over all imports in source
|
||||
for (const { absolutePath } of findAll('ImportDirective', solcOutput.sources[source].ast)) {
|
||||
// So files that only import without declaring anything cause issues, because they don't shop in in "pragma"
|
||||
// So files that only import without declaring anything cause issues, because they don't shop in "pragma"
|
||||
if (!pragma[absolutePath]) continue;
|
||||
// Check that the minVersion for source satisfies the requirements of the imported files
|
||||
if (!semver.satisfies(minVersion, pragma[absolutePath])) {
|
||||
|
||||
50
scripts/fetch-common-contracts.js
Executable file
50
scripts/fetch-common-contracts.js
Executable file
@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// This script snapshots the bytecode and ABI for the `hardhat/common-contracts.js` script.
|
||||
// - Bytecode is fetched directly from the blockchain by querying the provided client endpoint. If no endpoint is
|
||||
// provided, ethers default provider is used instead.
|
||||
// - ABI is fetched from etherscan's API using the provided etherscan API key. If no API key is provided, ABI will not
|
||||
// be fetched and saved.
|
||||
//
|
||||
// The produced artifacts are stored in the `output` folder ('test/bin' by default). For each contract, two files are
|
||||
// produced:
|
||||
// - `<name>.bytecode` containing the contract bytecode (in binary encoding)
|
||||
// - `<name>.abi` containing the ABI (in utf-8 encoding)
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { ethers } = require('ethers');
|
||||
const { request } = require('undici');
|
||||
const { hideBin } = require('yargs/helpers');
|
||||
const { argv } = require('yargs/yargs')(hideBin(process.argv))
|
||||
.env('')
|
||||
.options({
|
||||
output: { type: 'string', default: 'test/bin/' },
|
||||
client: { type: 'string' },
|
||||
etherscan: { type: 'string' },
|
||||
});
|
||||
|
||||
// List of contract names and addresses to fetch
|
||||
const config = {
|
||||
EntryPoint070: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
|
||||
SenderCreator070: '0xEFC2c1444eBCC4Db75e7613d20C6a62fF67A167C',
|
||||
EntryPoint080: '0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108',
|
||||
SenderCreator080: '0x449ED7C3e6Fee6a97311d4b55475DF59C44AdD33',
|
||||
};
|
||||
|
||||
Promise.all(
|
||||
Object.entries(config).flatMap(([name, addr]) =>
|
||||
Promise.all([
|
||||
argv.etherscan &&
|
||||
request(`https://api.etherscan.io/api?module=contract&action=getabi&address=${addr}&apikey=${argv.etherscan}`)
|
||||
.then(({ body }) => body.json())
|
||||
.then(({ result: abi }) => fs.writeFile(path.join(argv.output, `${name}.abi`), abi, 'utf-8', () => {})),
|
||||
ethers
|
||||
.getDefaultProvider(argv.client)
|
||||
.getCode(addr)
|
||||
.then(bytecode =>
|
||||
fs.writeFile(path.join(argv.output, `${name}.bytecode`), ethers.getBytes(bytecode), 'binary', () => {}),
|
||||
),
|
||||
]),
|
||||
),
|
||||
);
|
||||
@ -346,7 +346,7 @@ function unsafeMemoryAccess(${type}[] memory arr, uint256 pos) internal pure ret
|
||||
|
||||
const unsafeSetLength = type => `\
|
||||
/**
|
||||
* @dev Helper to set the length of an dynamic array. Directly writing to \`.length\` is forbidden.
|
||||
* @dev Helper to set the length of a dynamic array. Directly writing to \`.length\` is forbidden.
|
||||
*
|
||||
* WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
|
||||
*/
|
||||
|
||||
@ -119,7 +119,7 @@ function latestCheckpoint(${opts.historyTypeName} storage self) internal view re
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the number of checkpoint.
|
||||
* @dev Returns the number of checkpoints.
|
||||
*/
|
||||
function length(${opts.historyTypeName} storage self) internal view returns (uint256) {
|
||||
return self.${opts.checkpointFieldName}.length;
|
||||
|
||||
@ -14,7 +14,7 @@ import {Checkpoints} from "@openzeppelin/contracts/utils/structs/Checkpoints.sol
|
||||
const template = opts => `\
|
||||
using Checkpoints for Checkpoints.${opts.historyTypeName};
|
||||
|
||||
// Maximum gap between keys used during the fuzzing tests: the \`_prepareKeys\` function with make sure that
|
||||
// Maximum gap between keys used during the fuzzing tests: the \`_prepareKeys\` function will make sure that
|
||||
// key#n+1 is in the [key#n, key#n + _KEY_MAX_GAP] range.
|
||||
uint8 internal constant _KEY_MAX_GAP = 64;
|
||||
|
||||
@ -36,7 +36,7 @@ function _prepareKeys(${opts.keyTypeName}[] memory keys, ${opts.keyTypeName} max
|
||||
}
|
||||
}
|
||||
|
||||
function _assertLatestCheckpoint(bool exist, ${opts.keyTypeName} key, ${opts.valueTypeName} value) internal {
|
||||
function _assertLatestCheckpoint(bool exist, ${opts.keyTypeName} key, ${opts.valueTypeName} value) internal view {
|
||||
(bool _exist, ${opts.keyTypeName} _key, ${opts.valueTypeName} _value) = _ckpts.latestCheckpoint();
|
||||
assertEq(_exist, exist);
|
||||
assertEq(_key, key);
|
||||
|
||||
@ -17,6 +17,7 @@ import {EnumerableSet} from "./EnumerableSet.sol";
|
||||
* - Entries are added, removed, and checked for existence in constant time
|
||||
* (O(1)).
|
||||
* - Entries are enumerated in O(n). No guarantees are made on the ordering.
|
||||
* - Map can be cleared (all entries removed) in O(n).
|
||||
*
|
||||
* \`\`\`solidity
|
||||
* contract Example {
|
||||
@ -91,6 +92,20 @@ function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (
|
||||
return map._keys.remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Removes all the entries from a map. O(n).
|
||||
*
|
||||
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
|
||||
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
|
||||
*/
|
||||
function clear(Bytes32ToBytes32Map storage map) internal {
|
||||
uint256 len = length(map);
|
||||
for (uint256 i = 0; i < len; ++i) {
|
||||
delete map._values[map._keys.at(i)];
|
||||
}
|
||||
map._keys.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns true if the key is in the map. O(1).
|
||||
*/
|
||||
@ -188,6 +203,16 @@ function remove(${name} storage map, ${keyType} key) internal returns (bool) {
|
||||
return remove(map._inner, ${toBytes32(keyType, 'key')});
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Removes all the entries from a map. O(n).
|
||||
*
|
||||
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
|
||||
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
|
||||
*/
|
||||
function clear(${name} storage map) internal {
|
||||
clear(map._inner);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns true if the key is in the map. O(1).
|
||||
*/
|
||||
|
||||
@ -5,6 +5,8 @@ const { TYPES } = require('./EnumerableSet.opts');
|
||||
const header = `\
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Arrays} from "../Arrays.sol";
|
||||
|
||||
/**
|
||||
* @dev Library for managing
|
||||
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
|
||||
@ -15,6 +17,7 @@ pragma solidity ^0.8.20;
|
||||
* - 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.
|
||||
* - Set can be cleared (all elements removed) in O(n).
|
||||
*
|
||||
* \`\`\`solidity
|
||||
* contract Example {
|
||||
@ -117,6 +120,20 @@ function _remove(Set storage set, bytes32 value) private returns (bool) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Removes all the values from a set. O(n).
|
||||
*
|
||||
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
|
||||
* function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
|
||||
*/
|
||||
function _clear(Set storage set) private {
|
||||
uint256 len = _length(set);
|
||||
for (uint256 i = 0; i < len; ++i) {
|
||||
delete set._positions[set._values[i]];
|
||||
}
|
||||
Arrays.unsafeSetLength(set._values, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns true if the value is in the set. O(1).
|
||||
*/
|
||||
@ -185,6 +202,16 @@ function remove(${name} storage set, ${type} value) internal returns (bool) {
|
||||
return _remove(set._inner, ${toBytes32(type, 'value')});
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Removes all the values from a set. O(n).
|
||||
*
|
||||
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
|
||||
* function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
|
||||
*/
|
||||
function clear(${name} storage set) internal {
|
||||
_clear(set._inner);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns true if the value is in the set. O(1).
|
||||
*/
|
||||
|
||||
@ -20,7 +20,7 @@ pragma solidity ^0.8.20;
|
||||
* using SlotDerivation for bytes32;
|
||||
*
|
||||
* // Declare a namespace
|
||||
* string private constant _NAMESPACE = "<namespace>" // eg. OpenZeppelin.Slot
|
||||
* string private constant _NAMESPACE = "<namespace>"; // eg. OpenZeppelin.Slot
|
||||
*
|
||||
* function setValueInNamespace(uint256 key, address newValue) internal {
|
||||
* _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;
|
||||
|
||||
@ -45,7 +45,7 @@ function _assertDeriveArray(uint256 length, uint256 offset) public {
|
||||
const mapping = ({ type, name }) => `\
|
||||
mapping(${type} => bytes) private _${type}Mapping;
|
||||
|
||||
function testSymbolicDeriveMapping${name}(${type} key) public {
|
||||
function testSymbolicDeriveMapping${name}(${type} key) public view {
|
||||
bytes32 baseSlot;
|
||||
assembly {
|
||||
baseSlot := _${type}Mapping.slot
|
||||
@ -76,15 +76,15 @@ function testSymbolicDeriveMapping${name}Dirty(bytes32 dirtyKey) public {
|
||||
const boundedMapping = ({ type, name }) => `\
|
||||
mapping(${type} => bytes) private _${type}Mapping;
|
||||
|
||||
function testDeriveMapping${name}(${type} memory key) public {
|
||||
function testDeriveMapping${name}(${type} memory key) public view {
|
||||
_assertDeriveMapping${name}(key);
|
||||
}
|
||||
|
||||
function symbolicDeriveMapping${name}() public {
|
||||
function symbolicDeriveMapping${name}() public view {
|
||||
_assertDeriveMapping${name}(svm.create${name}(256, "DeriveMapping${name}Input"));
|
||||
}
|
||||
|
||||
function _assertDeriveMapping${name}(${type} memory key) internal {
|
||||
function _assertDeriveMapping${name}(${type} memory key) internal view {
|
||||
bytes32 baseSlot;
|
||||
assembly {
|
||||
baseSlot := _${type}Mapping.slot
|
||||
|
||||
@ -34,7 +34,7 @@ pragma solidity ^0.8.24;
|
||||
|
||||
const udvt = ({ type, name }) => `\
|
||||
/**
|
||||
* @dev UDVT that represent a slot holding a ${type}.
|
||||
* @dev UDVT that represents a slot holding ${type == 'address' ? 'an' : 'a'} ${type}.
|
||||
*/
|
||||
type ${name}Slot is bytes32;
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ examples_source_dir="contracts/mocks/docs"
|
||||
examples_target_dir="docs/modules/api/examples"
|
||||
|
||||
for f in "$examples_source_dir"/**/*.sol; do
|
||||
name="${f/#"$examples_source_dir/"/}"
|
||||
name="${f/#"$examples_source_dir"/}"
|
||||
mkdir -p "$examples_target_dir/$(dirname "$name")"
|
||||
sed -Ee '/^import/s|"(\.\./)+|"@openzeppelin/contracts/|' "$f" > "$examples_target_dir/$name"
|
||||
done
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if git status &>/dev/null; then git config core.hooksPath .githooks; fi
|
||||
@ -27,7 +27,7 @@ const formatted = changelog
|
||||
.replace(RELEASE_LINE_REGEX, (_, pr, entry) => (pr ? `- ${entry} (${pr})` : `- ${entry}`))
|
||||
// Add date to new version
|
||||
.replace(VERSION_TITLE_REGEX, `\n## $1 (${new Date().toISOString().split('T')[0]})`)
|
||||
// Conditionally allow vX.Y.Z.rc-.W sections only in prerelease
|
||||
// Conditionally allow vX.Y.Z-rc.W sections only in prerelease
|
||||
.replace(/^## \d\.\d\.\d-rc\S+[^]+?(?=^#)/gm, section => (isPrerelease ? section : ''));
|
||||
|
||||
fs.writeFileSync('CHANGELOG.md', formatted);
|
||||
|
||||
10
scripts/set-max-old-space-size.sh
Executable file
10
scripts/set-max-old-space-size.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# This script sets the node `--max-old-space-size` to 8192 if it is not set already.
|
||||
# All existing `NODE_OPTIONS` are retained as is.
|
||||
|
||||
export NODE_OPTIONS="${NODE_OPTIONS:-}"
|
||||
|
||||
if [ "${NODE_OPTIONS##*--max-old-space-size*}" = "$NODE_OPTIONS" ]; then
|
||||
export NODE_OPTIONS="${NODE_OPTIONS} --max-old-space-size=8192"
|
||||
fi
|
||||
@ -1,5 +1,8 @@
|
||||
{
|
||||
"name": "solhint-plugin-openzeppelin",
|
||||
"version": "0.0.0",
|
||||
"private": true
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"minimatch": "^3.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ index ff596b0c3..000000000
|
||||
-<!-- Make sure that you have reviewed the OpenZeppelin Contracts Contributor Guidelines. -->
|
||||
-<!-- https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/CONTRIBUTING.md -->
|
||||
diff --git a/README.md b/README.md
|
||||
index fa7b4e31e..4799b6376 100644
|
||||
index 60d0a430a..0e4f91a6d 100644
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -19,6 +19,9 @@
|
||||
@ -110,7 +110,7 @@ index fa7b4e31e..4799b6376 100644
|
||||
}
|
||||
```
|
||||
diff --git a/contracts/package.json b/contracts/package.json
|
||||
index 845e8c403..8dc181b91 100644
|
||||
index 3682eadeb..4f870d094 100644
|
||||
--- a/contracts/package.json
|
||||
+++ b/contracts/package.json
|
||||
@@ -1,5 +1,5 @@
|
||||
@ -118,7 +118,7 @@ index 845e8c403..8dc181b91 100644
|
||||
- "name": "@openzeppelin/contracts",
|
||||
+ "name": "@openzeppelin/contracts-upgradeable",
|
||||
"description": "Secure Smart Contract library for Solidity",
|
||||
"version": "5.0.2",
|
||||
"version": "5.2.0",
|
||||
"files": [
|
||||
@@ -13,7 +13,7 @@
|
||||
},
|
||||
@ -140,7 +140,7 @@ index 845e8c403..8dc181b91 100644
|
||||
+ }
|
||||
}
|
||||
diff --git a/contracts/utils/cryptography/EIP712.sol b/contracts/utils/cryptography/EIP712.sol
|
||||
index 77c4c8990..602467f40 100644
|
||||
index bcb67c87a..7195c3bbd 100644
|
||||
--- a/contracts/utils/cryptography/EIP712.sol
|
||||
+++ b/contracts/utils/cryptography/EIP712.sol
|
||||
@@ -4,7 +4,6 @@
|
||||
@ -151,7 +151,7 @@ index 77c4c8990..602467f40 100644
|
||||
import {IERC5267} from "../../interfaces/IERC5267.sol";
|
||||
|
||||
/**
|
||||
@@ -28,28 +27,18 @@ import {IERC5267} from "../../interfaces/IERC5267.sol";
|
||||
@@ -28,30 +27,18 @@ import {IERC5267} from "../../interfaces/IERC5267.sol";
|
||||
* NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain
|
||||
* separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the
|
||||
* separator from the immutable values, which is cheaper than accessing a cached version in cold storage.
|
||||
@ -177,14 +177,16 @@ index 77c4c8990..602467f40 100644
|
||||
|
||||
- ShortString private immutable _name;
|
||||
- ShortString private immutable _version;
|
||||
- // slither-disable-next-line constable-states
|
||||
- string private _nameFallback;
|
||||
- // slither-disable-next-line constable-states
|
||||
- string private _versionFallback;
|
||||
+ string private _name;
|
||||
+ string private _version;
|
||||
|
||||
/**
|
||||
* @dev Initializes the domain separator and parameter caches.
|
||||
@@ -64,29 +53,23 @@ abstract contract EIP712 is IERC5267 {
|
||||
@@ -66,29 +53,23 @@ abstract contract EIP712 is IERC5267 {
|
||||
* contract upgrade].
|
||||
*/
|
||||
constructor(string memory name, string memory version) {
|
||||
@ -222,7 +224,7 @@ index 77c4c8990..602467f40 100644
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,6 +108,10 @@ abstract contract EIP712 is IERC5267 {
|
||||
@@ -127,6 +108,10 @@ abstract contract EIP712 is IERC5267 {
|
||||
uint256[] memory extensions
|
||||
)
|
||||
{
|
||||
@ -233,7 +235,7 @@ index 77c4c8990..602467f40 100644
|
||||
return (
|
||||
hex"0f", // 01111
|
||||
_EIP712Name(),
|
||||
@@ -139,22 +126,62 @@ abstract contract EIP712 is IERC5267 {
|
||||
@@ -141,22 +126,62 @@ abstract contract EIP712 is IERC5267 {
|
||||
/**
|
||||
* @dev The name parameter for the EIP712 domain.
|
||||
*
|
||||
@ -307,10 +309,10 @@ index 77c4c8990..602467f40 100644
|
||||
}
|
||||
}
|
||||
diff --git a/package.json b/package.json
|
||||
index c4b358e10..96ab2559c 100644
|
||||
index f9e7d9205..c35020d51 100644
|
||||
--- a/package.json
|
||||
+++ b/package.json
|
||||
@@ -32,7 +32,7 @@
|
||||
@@ -34,7 +34,7 @@
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
Reference in New Issue
Block a user